xref: /f-stack/dpdk/app/test/test_graph_perf.c (revision 2d9fd380)
1*2d9fd380Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*2d9fd380Sjfb8856606  * Copyright(C) 2020 Marvell International Ltd.
3*2d9fd380Sjfb8856606  */
4*2d9fd380Sjfb8856606 #include <inttypes.h>
5*2d9fd380Sjfb8856606 #include <signal.h>
6*2d9fd380Sjfb8856606 #include <stdio.h>
7*2d9fd380Sjfb8856606 #include <unistd.h>
8*2d9fd380Sjfb8856606 
9*2d9fd380Sjfb8856606 #include <rte_common.h>
10*2d9fd380Sjfb8856606 #include <rte_cycles.h>
11*2d9fd380Sjfb8856606 #include <rte_errno.h>
12*2d9fd380Sjfb8856606 #include <rte_graph.h>
13*2d9fd380Sjfb8856606 #include <rte_graph_worker.h>
14*2d9fd380Sjfb8856606 #include <rte_lcore.h>
15*2d9fd380Sjfb8856606 #include <rte_malloc.h>
16*2d9fd380Sjfb8856606 #include <rte_mbuf.h>
17*2d9fd380Sjfb8856606 
18*2d9fd380Sjfb8856606 #include "test.h"
19*2d9fd380Sjfb8856606 
20*2d9fd380Sjfb8856606 #define TEST_GRAPH_PERF_MZ	     "graph_perf_data"
21*2d9fd380Sjfb8856606 #define TEST_GRAPH_SRC_NAME	     "test_graph_perf_source"
22*2d9fd380Sjfb8856606 #define TEST_GRAPH_SRC_BRST_ONE_NAME "test_graph_perf_source_one"
23*2d9fd380Sjfb8856606 #define TEST_GRAPH_WRK_NAME	     "test_graph_perf_worker"
24*2d9fd380Sjfb8856606 #define TEST_GRAPH_SNK_NAME	     "test_graph_perf_sink"
25*2d9fd380Sjfb8856606 
26*2d9fd380Sjfb8856606 #define SOURCES(map)	     RTE_DIM(map)
27*2d9fd380Sjfb8856606 #define STAGES(map)	     RTE_DIM(map)
28*2d9fd380Sjfb8856606 #define NODES_PER_STAGE(map) RTE_DIM(map[0])
29*2d9fd380Sjfb8856606 #define SINKS(map)	     RTE_DIM(map[0])
30*2d9fd380Sjfb8856606 
31*2d9fd380Sjfb8856606 #define MAX_EDGES_PER_NODE 7
32*2d9fd380Sjfb8856606 
33*2d9fd380Sjfb8856606 struct test_node_data {
34*2d9fd380Sjfb8856606 	uint8_t node_id;
35*2d9fd380Sjfb8856606 	uint8_t is_sink;
36*2d9fd380Sjfb8856606 	uint8_t next_nodes[MAX_EDGES_PER_NODE];
37*2d9fd380Sjfb8856606 	uint8_t next_percentage[MAX_EDGES_PER_NODE];
38*2d9fd380Sjfb8856606 };
39*2d9fd380Sjfb8856606 
40*2d9fd380Sjfb8856606 struct test_graph_perf {
41*2d9fd380Sjfb8856606 	uint16_t nb_nodes;
42*2d9fd380Sjfb8856606 	rte_graph_t graph_id;
43*2d9fd380Sjfb8856606 	struct test_node_data *node_data;
44*2d9fd380Sjfb8856606 };
45*2d9fd380Sjfb8856606 
46*2d9fd380Sjfb8856606 struct graph_lcore_data {
47*2d9fd380Sjfb8856606 	uint8_t done;
48*2d9fd380Sjfb8856606 	rte_graph_t graph_id;
49*2d9fd380Sjfb8856606 };
50*2d9fd380Sjfb8856606 
51*2d9fd380Sjfb8856606 static struct test_node_data *
graph_get_node_data(struct test_graph_perf * graph_data,rte_node_t id)52*2d9fd380Sjfb8856606 graph_get_node_data(struct test_graph_perf *graph_data, rte_node_t id)
53*2d9fd380Sjfb8856606 {
54*2d9fd380Sjfb8856606 	struct test_node_data *node_data = NULL;
55*2d9fd380Sjfb8856606 	int i;
56*2d9fd380Sjfb8856606 
57*2d9fd380Sjfb8856606 	for (i = 0; i < graph_data->nb_nodes; i++)
58*2d9fd380Sjfb8856606 		if (graph_data->node_data[i].node_id == id) {
59*2d9fd380Sjfb8856606 			node_data = &graph_data->node_data[i];
60*2d9fd380Sjfb8856606 			break;
61*2d9fd380Sjfb8856606 		}
62*2d9fd380Sjfb8856606 
63*2d9fd380Sjfb8856606 	return node_data;
64*2d9fd380Sjfb8856606 }
65*2d9fd380Sjfb8856606 
66*2d9fd380Sjfb8856606 static int
test_node_ctx_init(const struct rte_graph * graph,struct rte_node * node)67*2d9fd380Sjfb8856606 test_node_ctx_init(const struct rte_graph *graph, struct rte_node *node)
68*2d9fd380Sjfb8856606 {
69*2d9fd380Sjfb8856606 	struct test_graph_perf *graph_data;
70*2d9fd380Sjfb8856606 	struct test_node_data *node_data;
71*2d9fd380Sjfb8856606 	const struct rte_memzone *mz;
72*2d9fd380Sjfb8856606 	rte_node_t nid = node->id;
73*2d9fd380Sjfb8856606 	rte_edge_t edge = 0;
74*2d9fd380Sjfb8856606 	int i;
75*2d9fd380Sjfb8856606 
76*2d9fd380Sjfb8856606 	RTE_SET_USED(graph);
77*2d9fd380Sjfb8856606 
78*2d9fd380Sjfb8856606 	mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ);
79*2d9fd380Sjfb8856606 	if (mz == NULL)
80*2d9fd380Sjfb8856606 		return -ENOMEM;
81*2d9fd380Sjfb8856606 	graph_data = mz->addr;
82*2d9fd380Sjfb8856606 	node_data = graph_get_node_data(graph_data, nid);
83*2d9fd380Sjfb8856606 	node->ctx[0] = node->nb_edges;
84*2d9fd380Sjfb8856606 	for (i = 0; i < node->nb_edges && !node_data->is_sink; i++, edge++) {
85*2d9fd380Sjfb8856606 		node->ctx[i + 1] = edge;
86*2d9fd380Sjfb8856606 		node->ctx[i + 9] = node_data->next_percentage[i];
87*2d9fd380Sjfb8856606 	}
88*2d9fd380Sjfb8856606 
89*2d9fd380Sjfb8856606 	return 0;
90*2d9fd380Sjfb8856606 }
91*2d9fd380Sjfb8856606 
92*2d9fd380Sjfb8856606 /* Source node function */
93*2d9fd380Sjfb8856606 static uint16_t
test_perf_node_worker_source(struct rte_graph * graph,struct rte_node * node,void ** objs,uint16_t nb_objs)94*2d9fd380Sjfb8856606 test_perf_node_worker_source(struct rte_graph *graph, struct rte_node *node,
95*2d9fd380Sjfb8856606 			     void **objs, uint16_t nb_objs)
96*2d9fd380Sjfb8856606 {
97*2d9fd380Sjfb8856606 	uint16_t count;
98*2d9fd380Sjfb8856606 	int i;
99*2d9fd380Sjfb8856606 
100*2d9fd380Sjfb8856606 	RTE_SET_USED(objs);
101*2d9fd380Sjfb8856606 	RTE_SET_USED(nb_objs);
102*2d9fd380Sjfb8856606 
103*2d9fd380Sjfb8856606 	/* Create a proportional stream for every next */
104*2d9fd380Sjfb8856606 	for (i = 0; i < node->ctx[0]; i++) {
105*2d9fd380Sjfb8856606 		count = (node->ctx[i + 9] * RTE_GRAPH_BURST_SIZE) / 100;
106*2d9fd380Sjfb8856606 		rte_node_next_stream_get(graph, node, node->ctx[i + 1], count);
107*2d9fd380Sjfb8856606 		rte_node_next_stream_put(graph, node, node->ctx[i + 1], count);
108*2d9fd380Sjfb8856606 	}
109*2d9fd380Sjfb8856606 
110*2d9fd380Sjfb8856606 	return RTE_GRAPH_BURST_SIZE;
111*2d9fd380Sjfb8856606 }
112*2d9fd380Sjfb8856606 
113*2d9fd380Sjfb8856606 static struct rte_node_register test_graph_perf_source = {
114*2d9fd380Sjfb8856606 	.name = TEST_GRAPH_SRC_NAME,
115*2d9fd380Sjfb8856606 	.process = test_perf_node_worker_source,
116*2d9fd380Sjfb8856606 	.flags = RTE_NODE_SOURCE_F,
117*2d9fd380Sjfb8856606 	.init = test_node_ctx_init,
118*2d9fd380Sjfb8856606 };
119*2d9fd380Sjfb8856606 
120*2d9fd380Sjfb8856606 RTE_NODE_REGISTER(test_graph_perf_source);
121*2d9fd380Sjfb8856606 
122*2d9fd380Sjfb8856606 static uint16_t
test_perf_node_worker_source_burst_one(struct rte_graph * graph,struct rte_node * node,void ** objs,uint16_t nb_objs)123*2d9fd380Sjfb8856606 test_perf_node_worker_source_burst_one(struct rte_graph *graph,
124*2d9fd380Sjfb8856606 				       struct rte_node *node, void **objs,
125*2d9fd380Sjfb8856606 				       uint16_t nb_objs)
126*2d9fd380Sjfb8856606 {
127*2d9fd380Sjfb8856606 	uint16_t count;
128*2d9fd380Sjfb8856606 	int i;
129*2d9fd380Sjfb8856606 
130*2d9fd380Sjfb8856606 	RTE_SET_USED(objs);
131*2d9fd380Sjfb8856606 	RTE_SET_USED(nb_objs);
132*2d9fd380Sjfb8856606 
133*2d9fd380Sjfb8856606 	/* Create a proportional stream for every next */
134*2d9fd380Sjfb8856606 	for (i = 0; i < node->ctx[0]; i++) {
135*2d9fd380Sjfb8856606 		count = (node->ctx[i + 9]) / 100;
136*2d9fd380Sjfb8856606 		rte_node_next_stream_get(graph, node, node->ctx[i + 1], count);
137*2d9fd380Sjfb8856606 		rte_node_next_stream_put(graph, node, node->ctx[i + 1], count);
138*2d9fd380Sjfb8856606 	}
139*2d9fd380Sjfb8856606 
140*2d9fd380Sjfb8856606 	return 1;
141*2d9fd380Sjfb8856606 }
142*2d9fd380Sjfb8856606 
143*2d9fd380Sjfb8856606 static struct rte_node_register test_graph_perf_source_burst_one = {
144*2d9fd380Sjfb8856606 	.name = TEST_GRAPH_SRC_BRST_ONE_NAME,
145*2d9fd380Sjfb8856606 	.process = test_perf_node_worker_source_burst_one,
146*2d9fd380Sjfb8856606 	.flags = RTE_NODE_SOURCE_F,
147*2d9fd380Sjfb8856606 	.init = test_node_ctx_init,
148*2d9fd380Sjfb8856606 };
149*2d9fd380Sjfb8856606 
150*2d9fd380Sjfb8856606 RTE_NODE_REGISTER(test_graph_perf_source_burst_one);
151*2d9fd380Sjfb8856606 
152*2d9fd380Sjfb8856606 /* Worker node function */
153*2d9fd380Sjfb8856606 static uint16_t
test_perf_node_worker(struct rte_graph * graph,struct rte_node * node,void ** objs,uint16_t nb_objs)154*2d9fd380Sjfb8856606 test_perf_node_worker(struct rte_graph *graph, struct rte_node *node,
155*2d9fd380Sjfb8856606 		      void **objs, uint16_t nb_objs)
156*2d9fd380Sjfb8856606 {
157*2d9fd380Sjfb8856606 	uint16_t next = 0;
158*2d9fd380Sjfb8856606 	uint16_t enq = 0;
159*2d9fd380Sjfb8856606 	uint16_t count;
160*2d9fd380Sjfb8856606 	int i;
161*2d9fd380Sjfb8856606 
162*2d9fd380Sjfb8856606 	/* Move stream for single next node */
163*2d9fd380Sjfb8856606 	if (node->ctx[0] == 1) {
164*2d9fd380Sjfb8856606 		rte_node_next_stream_move(graph, node, node->ctx[1]);
165*2d9fd380Sjfb8856606 		return nb_objs;
166*2d9fd380Sjfb8856606 	}
167*2d9fd380Sjfb8856606 
168*2d9fd380Sjfb8856606 	/* Enqueue objects to next nodes proportionally */
169*2d9fd380Sjfb8856606 	for (i = 0; i < node->ctx[0]; i++) {
170*2d9fd380Sjfb8856606 		next = node->ctx[i + 1];
171*2d9fd380Sjfb8856606 		count = (node->ctx[i + 9] * nb_objs) / 100;
172*2d9fd380Sjfb8856606 		enq += count;
173*2d9fd380Sjfb8856606 		while (count) {
174*2d9fd380Sjfb8856606 			switch (count & (4 - 1)) {
175*2d9fd380Sjfb8856606 			case 0:
176*2d9fd380Sjfb8856606 				rte_node_enqueue_x4(graph, node, next, objs[0],
177*2d9fd380Sjfb8856606 						    objs[1], objs[2], objs[3]);
178*2d9fd380Sjfb8856606 				objs += 4;
179*2d9fd380Sjfb8856606 				count -= 4;
180*2d9fd380Sjfb8856606 				break;
181*2d9fd380Sjfb8856606 			case 1:
182*2d9fd380Sjfb8856606 				rte_node_enqueue_x1(graph, node, next, objs[0]);
183*2d9fd380Sjfb8856606 				objs += 1;
184*2d9fd380Sjfb8856606 				count -= 1;
185*2d9fd380Sjfb8856606 				break;
186*2d9fd380Sjfb8856606 			case 2:
187*2d9fd380Sjfb8856606 				rte_node_enqueue_x2(graph, node, next, objs[0],
188*2d9fd380Sjfb8856606 						    objs[1]);
189*2d9fd380Sjfb8856606 				objs += 2;
190*2d9fd380Sjfb8856606 				count -= 2;
191*2d9fd380Sjfb8856606 				break;
192*2d9fd380Sjfb8856606 			case 3:
193*2d9fd380Sjfb8856606 				rte_node_enqueue_x2(graph, node, next, objs[0],
194*2d9fd380Sjfb8856606 						    objs[1]);
195*2d9fd380Sjfb8856606 				rte_node_enqueue_x1(graph, node, next, objs[0]);
196*2d9fd380Sjfb8856606 				objs += 3;
197*2d9fd380Sjfb8856606 				count -= 3;
198*2d9fd380Sjfb8856606 				break;
199*2d9fd380Sjfb8856606 			}
200*2d9fd380Sjfb8856606 		}
201*2d9fd380Sjfb8856606 	}
202*2d9fd380Sjfb8856606 
203*2d9fd380Sjfb8856606 	if (enq != nb_objs)
204*2d9fd380Sjfb8856606 		rte_node_enqueue(graph, node, next, objs, nb_objs - enq);
205*2d9fd380Sjfb8856606 
206*2d9fd380Sjfb8856606 	return nb_objs;
207*2d9fd380Sjfb8856606 }
208*2d9fd380Sjfb8856606 
209*2d9fd380Sjfb8856606 static struct rte_node_register test_graph_perf_worker = {
210*2d9fd380Sjfb8856606 	.name = TEST_GRAPH_WRK_NAME,
211*2d9fd380Sjfb8856606 	.process = test_perf_node_worker,
212*2d9fd380Sjfb8856606 	.init = test_node_ctx_init,
213*2d9fd380Sjfb8856606 };
214*2d9fd380Sjfb8856606 
215*2d9fd380Sjfb8856606 RTE_NODE_REGISTER(test_graph_perf_worker);
216*2d9fd380Sjfb8856606 
217*2d9fd380Sjfb8856606 /* Last node in graph a.k.a sink node */
218*2d9fd380Sjfb8856606 static uint16_t
test_perf_node_sink(struct rte_graph * graph,struct rte_node * node,void ** objs,uint16_t nb_objs)219*2d9fd380Sjfb8856606 test_perf_node_sink(struct rte_graph *graph, struct rte_node *node, void **objs,
220*2d9fd380Sjfb8856606 		    uint16_t nb_objs)
221*2d9fd380Sjfb8856606 {
222*2d9fd380Sjfb8856606 	RTE_SET_USED(graph);
223*2d9fd380Sjfb8856606 	RTE_SET_USED(node);
224*2d9fd380Sjfb8856606 	RTE_SET_USED(objs);
225*2d9fd380Sjfb8856606 	RTE_SET_USED(nb_objs);
226*2d9fd380Sjfb8856606 
227*2d9fd380Sjfb8856606 	return nb_objs;
228*2d9fd380Sjfb8856606 }
229*2d9fd380Sjfb8856606 
230*2d9fd380Sjfb8856606 static struct rte_node_register test_graph_perf_sink = {
231*2d9fd380Sjfb8856606 	.name = TEST_GRAPH_SNK_NAME,
232*2d9fd380Sjfb8856606 	.process = test_perf_node_sink,
233*2d9fd380Sjfb8856606 	.init = test_node_ctx_init,
234*2d9fd380Sjfb8856606 };
235*2d9fd380Sjfb8856606 
236*2d9fd380Sjfb8856606 RTE_NODE_REGISTER(test_graph_perf_sink);
237*2d9fd380Sjfb8856606 
238*2d9fd380Sjfb8856606 static int
graph_perf_setup(void)239*2d9fd380Sjfb8856606 graph_perf_setup(void)
240*2d9fd380Sjfb8856606 {
241*2d9fd380Sjfb8856606 	if (rte_lcore_count() < 2) {
242*2d9fd380Sjfb8856606 		printf("Test requires at least 2 lcores\n");
243*2d9fd380Sjfb8856606 		return TEST_SKIPPED;
244*2d9fd380Sjfb8856606 	}
245*2d9fd380Sjfb8856606 
246*2d9fd380Sjfb8856606 	return 0;
247*2d9fd380Sjfb8856606 }
248*2d9fd380Sjfb8856606 
249*2d9fd380Sjfb8856606 static void
graph_perf_teardown(void)250*2d9fd380Sjfb8856606 graph_perf_teardown(void)
251*2d9fd380Sjfb8856606 {
252*2d9fd380Sjfb8856606 }
253*2d9fd380Sjfb8856606 
254*2d9fd380Sjfb8856606 static inline rte_node_t
graph_node_get(const char * pname,char * nname)255*2d9fd380Sjfb8856606 graph_node_get(const char *pname, char *nname)
256*2d9fd380Sjfb8856606 {
257*2d9fd380Sjfb8856606 	rte_node_t pnode_id = rte_node_from_name(pname);
258*2d9fd380Sjfb8856606 	char lookup_name[RTE_NODE_NAMESIZE];
259*2d9fd380Sjfb8856606 	rte_node_t node_id;
260*2d9fd380Sjfb8856606 
261*2d9fd380Sjfb8856606 	snprintf(lookup_name, RTE_NODE_NAMESIZE, "%s-%s", pname, nname);
262*2d9fd380Sjfb8856606 	node_id = rte_node_from_name(lookup_name);
263*2d9fd380Sjfb8856606 
264*2d9fd380Sjfb8856606 	if (node_id != RTE_NODE_ID_INVALID) {
265*2d9fd380Sjfb8856606 		if (rte_node_edge_count(node_id))
266*2d9fd380Sjfb8856606 			rte_node_edge_shrink(node_id, 0);
267*2d9fd380Sjfb8856606 		return node_id;
268*2d9fd380Sjfb8856606 	}
269*2d9fd380Sjfb8856606 
270*2d9fd380Sjfb8856606 	return rte_node_clone(pnode_id, nname);
271*2d9fd380Sjfb8856606 }
272*2d9fd380Sjfb8856606 
273*2d9fd380Sjfb8856606 static uint16_t
graph_node_count_edges(uint32_t stage,uint16_t node,uint16_t nodes_per_stage,uint8_t edge_map[][nodes_per_stage][nodes_per_stage],char * ename[],struct test_node_data * node_data,rte_node_t ** node_map)274*2d9fd380Sjfb8856606 graph_node_count_edges(uint32_t stage, uint16_t node, uint16_t nodes_per_stage,
275*2d9fd380Sjfb8856606 		       uint8_t edge_map[][nodes_per_stage][nodes_per_stage],
276*2d9fd380Sjfb8856606 		       char *ename[], struct test_node_data *node_data,
277*2d9fd380Sjfb8856606 		       rte_node_t **node_map)
278*2d9fd380Sjfb8856606 {
279*2d9fd380Sjfb8856606 	uint8_t total_percent = 0;
280*2d9fd380Sjfb8856606 	uint16_t edges = 0;
281*2d9fd380Sjfb8856606 	int i;
282*2d9fd380Sjfb8856606 
283*2d9fd380Sjfb8856606 	for (i = 0; i < nodes_per_stage && edges < MAX_EDGES_PER_NODE; i++) {
284*2d9fd380Sjfb8856606 		if (edge_map[stage + 1][i][node]) {
285*2d9fd380Sjfb8856606 			ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE);
286*2d9fd380Sjfb8856606 			snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s",
287*2d9fd380Sjfb8856606 				 rte_node_id_to_name(node_map[stage + 1][i]));
288*2d9fd380Sjfb8856606 			node_data->next_nodes[edges] = node_map[stage + 1][i];
289*2d9fd380Sjfb8856606 			node_data->next_percentage[edges] =
290*2d9fd380Sjfb8856606 				edge_map[stage + 1][i][node];
291*2d9fd380Sjfb8856606 			edges++;
292*2d9fd380Sjfb8856606 			total_percent += edge_map[stage + 1][i][node];
293*2d9fd380Sjfb8856606 		}
294*2d9fd380Sjfb8856606 	}
295*2d9fd380Sjfb8856606 
296*2d9fd380Sjfb8856606 	if (edges >= MAX_EDGES_PER_NODE || (edges && total_percent != 100)) {
297*2d9fd380Sjfb8856606 		for (i = 0; i < edges; i++)
298*2d9fd380Sjfb8856606 			free(ename[i]);
299*2d9fd380Sjfb8856606 		return RTE_EDGE_ID_INVALID;
300*2d9fd380Sjfb8856606 	}
301*2d9fd380Sjfb8856606 
302*2d9fd380Sjfb8856606 	return edges;
303*2d9fd380Sjfb8856606 }
304*2d9fd380Sjfb8856606 
305*2d9fd380Sjfb8856606 static int
graph_init(const char * gname,uint8_t nb_srcs,uint8_t nb_sinks,uint32_t stages,uint16_t nodes_per_stage,uint8_t src_map[][nodes_per_stage],uint8_t snk_map[][nb_sinks],uint8_t edge_map[][nodes_per_stage][nodes_per_stage],uint8_t burst_one)306*2d9fd380Sjfb8856606 graph_init(const char *gname, uint8_t nb_srcs, uint8_t nb_sinks,
307*2d9fd380Sjfb8856606 	   uint32_t stages, uint16_t nodes_per_stage,
308*2d9fd380Sjfb8856606 	   uint8_t src_map[][nodes_per_stage], uint8_t snk_map[][nb_sinks],
309*2d9fd380Sjfb8856606 	   uint8_t edge_map[][nodes_per_stage][nodes_per_stage],
310*2d9fd380Sjfb8856606 	   uint8_t burst_one)
311*2d9fd380Sjfb8856606 {
312*2d9fd380Sjfb8856606 	struct test_graph_perf *graph_data;
313*2d9fd380Sjfb8856606 	char nname[RTE_NODE_NAMESIZE / 2];
314*2d9fd380Sjfb8856606 	struct test_node_data *node_data;
315*2d9fd380Sjfb8856606 	char *ename[nodes_per_stage];
316*2d9fd380Sjfb8856606 	struct rte_graph_param gconf;
317*2d9fd380Sjfb8856606 	const struct rte_memzone *mz;
318*2d9fd380Sjfb8856606 	uint8_t total_percent = 0;
319*2d9fd380Sjfb8856606 	rte_node_t *src_nodes;
320*2d9fd380Sjfb8856606 	rte_node_t *snk_nodes;
321*2d9fd380Sjfb8856606 	rte_node_t **node_map;
322*2d9fd380Sjfb8856606 	char **node_patterns;
323*2d9fd380Sjfb8856606 	rte_graph_t graph_id;
324*2d9fd380Sjfb8856606 	rte_edge_t edges;
325*2d9fd380Sjfb8856606 	rte_edge_t count;
326*2d9fd380Sjfb8856606 	uint32_t i, j, k;
327*2d9fd380Sjfb8856606 
328*2d9fd380Sjfb8856606 	mz = rte_memzone_reserve(TEST_GRAPH_PERF_MZ,
329*2d9fd380Sjfb8856606 				 sizeof(struct test_graph_perf), 0, 0);
330*2d9fd380Sjfb8856606 	if (mz == NULL) {
331*2d9fd380Sjfb8856606 		printf("Failed to allocate graph common memory\n");
332*2d9fd380Sjfb8856606 		return -ENOMEM;
333*2d9fd380Sjfb8856606 	}
334*2d9fd380Sjfb8856606 
335*2d9fd380Sjfb8856606 	graph_data = mz->addr;
336*2d9fd380Sjfb8856606 	graph_data->nb_nodes = 0;
337*2d9fd380Sjfb8856606 	graph_data->node_data =
338*2d9fd380Sjfb8856606 		malloc(sizeof(struct test_node_data) *
339*2d9fd380Sjfb8856606 		       (nb_srcs + nb_sinks + stages * nodes_per_stage));
340*2d9fd380Sjfb8856606 	if (graph_data->node_data == NULL) {
341*2d9fd380Sjfb8856606 		printf("Failed to reserve memzone for graph data\n");
342*2d9fd380Sjfb8856606 		goto memzone_free;
343*2d9fd380Sjfb8856606 	}
344*2d9fd380Sjfb8856606 
345*2d9fd380Sjfb8856606 	node_patterns = malloc(sizeof(char *) *
346*2d9fd380Sjfb8856606 			       (nb_srcs + nb_sinks + stages * nodes_per_stage));
347*2d9fd380Sjfb8856606 	if (node_patterns == NULL) {
348*2d9fd380Sjfb8856606 		printf("Failed to reserve memory for node patterns\n");
349*2d9fd380Sjfb8856606 		goto data_free;
350*2d9fd380Sjfb8856606 	}
351*2d9fd380Sjfb8856606 
352*2d9fd380Sjfb8856606 	src_nodes = malloc(sizeof(rte_node_t) * nb_srcs);
353*2d9fd380Sjfb8856606 	if (src_nodes == NULL) {
354*2d9fd380Sjfb8856606 		printf("Failed to reserve memory for src nodes\n");
355*2d9fd380Sjfb8856606 		goto pattern_free;
356*2d9fd380Sjfb8856606 	}
357*2d9fd380Sjfb8856606 
358*2d9fd380Sjfb8856606 	snk_nodes = malloc(sizeof(rte_node_t) * nb_sinks);
359*2d9fd380Sjfb8856606 	if (snk_nodes == NULL) {
360*2d9fd380Sjfb8856606 		printf("Failed to reserve memory for snk nodes\n");
361*2d9fd380Sjfb8856606 		goto src_free;
362*2d9fd380Sjfb8856606 	}
363*2d9fd380Sjfb8856606 
364*2d9fd380Sjfb8856606 	node_map = malloc(sizeof(rte_node_t *) * stages +
365*2d9fd380Sjfb8856606 			  sizeof(rte_node_t) * nodes_per_stage * stages);
366*2d9fd380Sjfb8856606 	if (node_map == NULL) {
367*2d9fd380Sjfb8856606 		printf("Failed to reserve memory for node map\n");
368*2d9fd380Sjfb8856606 		goto snk_free;
369*2d9fd380Sjfb8856606 	}
370*2d9fd380Sjfb8856606 
371*2d9fd380Sjfb8856606 	/* Setup the Graph */
372*2d9fd380Sjfb8856606 	for (i = 0; i < stages; i++) {
373*2d9fd380Sjfb8856606 		node_map[i] =
374*2d9fd380Sjfb8856606 			(rte_node_t *)(node_map + stages) + nodes_per_stage * i;
375*2d9fd380Sjfb8856606 		for (j = 0; j < nodes_per_stage; j++) {
376*2d9fd380Sjfb8856606 			total_percent = 0;
377*2d9fd380Sjfb8856606 			for (k = 0; k < nodes_per_stage; k++)
378*2d9fd380Sjfb8856606 				total_percent += edge_map[i][j][k];
379*2d9fd380Sjfb8856606 			if (!total_percent)
380*2d9fd380Sjfb8856606 				continue;
381*2d9fd380Sjfb8856606 			node_patterns[graph_data->nb_nodes] =
382*2d9fd380Sjfb8856606 				malloc(RTE_NODE_NAMESIZE);
383*2d9fd380Sjfb8856606 			if (node_patterns[graph_data->nb_nodes] == NULL) {
384*2d9fd380Sjfb8856606 				printf("Failed to create memory for pattern\n");
385*2d9fd380Sjfb8856606 				goto pattern_name_free;
386*2d9fd380Sjfb8856606 			}
387*2d9fd380Sjfb8856606 
388*2d9fd380Sjfb8856606 			/* Clone a worker node */
389*2d9fd380Sjfb8856606 			snprintf(nname, sizeof(nname), "%d-%d", i, j);
390*2d9fd380Sjfb8856606 			node_map[i][j] =
391*2d9fd380Sjfb8856606 				graph_node_get(TEST_GRAPH_WRK_NAME, nname);
392*2d9fd380Sjfb8856606 			if (node_map[i][j] == RTE_NODE_ID_INVALID) {
393*2d9fd380Sjfb8856606 				printf("Failed to create node[%s]\n", nname);
394*2d9fd380Sjfb8856606 				graph_data->nb_nodes++;
395*2d9fd380Sjfb8856606 				goto pattern_name_free;
396*2d9fd380Sjfb8856606 			}
397*2d9fd380Sjfb8856606 			snprintf(node_patterns[graph_data->nb_nodes],
398*2d9fd380Sjfb8856606 				 RTE_NODE_NAMESIZE, "%s",
399*2d9fd380Sjfb8856606 				 rte_node_id_to_name(node_map[i][j]));
400*2d9fd380Sjfb8856606 			node_data =
401*2d9fd380Sjfb8856606 				&graph_data->node_data[graph_data->nb_nodes];
402*2d9fd380Sjfb8856606 			node_data->node_id = node_map[i][j];
403*2d9fd380Sjfb8856606 			node_data->is_sink = false;
404*2d9fd380Sjfb8856606 			graph_data->nb_nodes++;
405*2d9fd380Sjfb8856606 		}
406*2d9fd380Sjfb8856606 	}
407*2d9fd380Sjfb8856606 
408*2d9fd380Sjfb8856606 	for (i = 0; i < stages - 1; i++) {
409*2d9fd380Sjfb8856606 		for (j = 0; j < nodes_per_stage; j++) {
410*2d9fd380Sjfb8856606 			/* Count edges i.e connections of worker node to next */
411*2d9fd380Sjfb8856606 			node_data =
412*2d9fd380Sjfb8856606 				graph_get_node_data(graph_data, node_map[i][j]);
413*2d9fd380Sjfb8856606 			edges = graph_node_count_edges(i, j, nodes_per_stage,
414*2d9fd380Sjfb8856606 						       edge_map, ename,
415*2d9fd380Sjfb8856606 						       node_data, node_map);
416*2d9fd380Sjfb8856606 			if (edges == RTE_EDGE_ID_INVALID) {
417*2d9fd380Sjfb8856606 				printf("Invalid edge configuration\n");
418*2d9fd380Sjfb8856606 				goto pattern_name_free;
419*2d9fd380Sjfb8856606 			}
420*2d9fd380Sjfb8856606 			if (!edges)
421*2d9fd380Sjfb8856606 				continue;
422*2d9fd380Sjfb8856606 
423*2d9fd380Sjfb8856606 			/* Connect a node in stage 'i' to nodes
424*2d9fd380Sjfb8856606 			 * in stage 'i + 1' with edges.
425*2d9fd380Sjfb8856606 			 */
426*2d9fd380Sjfb8856606 			count = rte_node_edge_update(
427*2d9fd380Sjfb8856606 				node_map[i][j], 0,
428*2d9fd380Sjfb8856606 				(const char **)(uintptr_t)ename, edges);
429*2d9fd380Sjfb8856606 			for (k = 0; k < edges; k++)
430*2d9fd380Sjfb8856606 				free(ename[k]);
431*2d9fd380Sjfb8856606 			if (count != edges) {
432*2d9fd380Sjfb8856606 				printf("Couldn't add edges %d %d\n", edges,
433*2d9fd380Sjfb8856606 				       count);
434*2d9fd380Sjfb8856606 				goto pattern_name_free;
435*2d9fd380Sjfb8856606 			}
436*2d9fd380Sjfb8856606 		}
437*2d9fd380Sjfb8856606 	}
438*2d9fd380Sjfb8856606 
439*2d9fd380Sjfb8856606 	/* Setup Source nodes */
440*2d9fd380Sjfb8856606 	for (i = 0; i < nb_srcs; i++) {
441*2d9fd380Sjfb8856606 		edges = 0;
442*2d9fd380Sjfb8856606 		total_percent = 0;
443*2d9fd380Sjfb8856606 		node_patterns[graph_data->nb_nodes] = malloc(RTE_NODE_NAMESIZE);
444*2d9fd380Sjfb8856606 		if (node_patterns[graph_data->nb_nodes] == NULL) {
445*2d9fd380Sjfb8856606 			printf("Failed to create memory for pattern\n");
446*2d9fd380Sjfb8856606 			goto pattern_name_free;
447*2d9fd380Sjfb8856606 		}
448*2d9fd380Sjfb8856606 		/* Clone a source node */
449*2d9fd380Sjfb8856606 		snprintf(nname, sizeof(nname), "%d", i);
450*2d9fd380Sjfb8856606 		src_nodes[i] =
451*2d9fd380Sjfb8856606 			graph_node_get(burst_one ? TEST_GRAPH_SRC_BRST_ONE_NAME
452*2d9fd380Sjfb8856606 						 : TEST_GRAPH_SRC_NAME,
453*2d9fd380Sjfb8856606 				       nname);
454*2d9fd380Sjfb8856606 		if (src_nodes[i] == RTE_NODE_ID_INVALID) {
455*2d9fd380Sjfb8856606 			printf("Failed to create node[%s]\n", nname);
456*2d9fd380Sjfb8856606 			graph_data->nb_nodes++;
457*2d9fd380Sjfb8856606 			goto pattern_name_free;
458*2d9fd380Sjfb8856606 		}
459*2d9fd380Sjfb8856606 		snprintf(node_patterns[graph_data->nb_nodes], RTE_NODE_NAMESIZE,
460*2d9fd380Sjfb8856606 			 "%s", rte_node_id_to_name(src_nodes[i]));
461*2d9fd380Sjfb8856606 		node_data = &graph_data->node_data[graph_data->nb_nodes];
462*2d9fd380Sjfb8856606 		node_data->node_id = src_nodes[i];
463*2d9fd380Sjfb8856606 		node_data->is_sink = false;
464*2d9fd380Sjfb8856606 		graph_data->nb_nodes++;
465*2d9fd380Sjfb8856606 
466*2d9fd380Sjfb8856606 		/* Prepare next node list  to connect to */
467*2d9fd380Sjfb8856606 		for (j = 0; j < nodes_per_stage; j++) {
468*2d9fd380Sjfb8856606 			if (!src_map[i][j])
469*2d9fd380Sjfb8856606 				continue;
470*2d9fd380Sjfb8856606 			ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE);
471*2d9fd380Sjfb8856606 			snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s",
472*2d9fd380Sjfb8856606 				 rte_node_id_to_name(node_map[0][j]));
473*2d9fd380Sjfb8856606 			node_data->next_nodes[edges] = node_map[0][j];
474*2d9fd380Sjfb8856606 			node_data->next_percentage[edges] = src_map[i][j];
475*2d9fd380Sjfb8856606 			edges++;
476*2d9fd380Sjfb8856606 			total_percent += src_map[i][j];
477*2d9fd380Sjfb8856606 		}
478*2d9fd380Sjfb8856606 
479*2d9fd380Sjfb8856606 		if (!edges)
480*2d9fd380Sjfb8856606 			continue;
481*2d9fd380Sjfb8856606 		if (edges >= MAX_EDGES_PER_NODE || total_percent != 100) {
482*2d9fd380Sjfb8856606 			printf("Invalid edge configuration\n");
483*2d9fd380Sjfb8856606 			for (j = 0; j < edges; j++)
484*2d9fd380Sjfb8856606 				free(ename[j]);
485*2d9fd380Sjfb8856606 			goto pattern_name_free;
486*2d9fd380Sjfb8856606 		}
487*2d9fd380Sjfb8856606 
488*2d9fd380Sjfb8856606 		/* Connect to list of next nodes using edges */
489*2d9fd380Sjfb8856606 		count = rte_node_edge_update(src_nodes[i], 0,
490*2d9fd380Sjfb8856606 					     (const char **)(uintptr_t)ename,
491*2d9fd380Sjfb8856606 					     edges);
492*2d9fd380Sjfb8856606 		for (k = 0; k < edges; k++)
493*2d9fd380Sjfb8856606 			free(ename[k]);
494*2d9fd380Sjfb8856606 		if (count != edges) {
495*2d9fd380Sjfb8856606 			printf("Couldn't add edges %d %d\n", edges, count);
496*2d9fd380Sjfb8856606 			goto pattern_name_free;
497*2d9fd380Sjfb8856606 		}
498*2d9fd380Sjfb8856606 	}
499*2d9fd380Sjfb8856606 
500*2d9fd380Sjfb8856606 	/* Setup Sink nodes */
501*2d9fd380Sjfb8856606 	for (i = 0; i < nb_sinks; i++) {
502*2d9fd380Sjfb8856606 		node_patterns[graph_data->nb_nodes] = malloc(RTE_NODE_NAMESIZE);
503*2d9fd380Sjfb8856606 		if (node_patterns[graph_data->nb_nodes] == NULL) {
504*2d9fd380Sjfb8856606 			printf("Failed to create memory for pattern\n");
505*2d9fd380Sjfb8856606 			goto pattern_name_free;
506*2d9fd380Sjfb8856606 		}
507*2d9fd380Sjfb8856606 
508*2d9fd380Sjfb8856606 		/* Clone a sink node */
509*2d9fd380Sjfb8856606 		snprintf(nname, sizeof(nname), "%d", i);
510*2d9fd380Sjfb8856606 		snk_nodes[i] = graph_node_get(TEST_GRAPH_SNK_NAME, nname);
511*2d9fd380Sjfb8856606 		if (snk_nodes[i] == RTE_NODE_ID_INVALID) {
512*2d9fd380Sjfb8856606 			printf("Failed to create node[%s]\n", nname);
513*2d9fd380Sjfb8856606 			graph_data->nb_nodes++;
514*2d9fd380Sjfb8856606 			goto pattern_name_free;
515*2d9fd380Sjfb8856606 		}
516*2d9fd380Sjfb8856606 		snprintf(node_patterns[graph_data->nb_nodes], RTE_NODE_NAMESIZE,
517*2d9fd380Sjfb8856606 			 "%s", rte_node_id_to_name(snk_nodes[i]));
518*2d9fd380Sjfb8856606 		node_data = &graph_data->node_data[graph_data->nb_nodes];
519*2d9fd380Sjfb8856606 		node_data->node_id = snk_nodes[i];
520*2d9fd380Sjfb8856606 		node_data->is_sink = true;
521*2d9fd380Sjfb8856606 		graph_data->nb_nodes++;
522*2d9fd380Sjfb8856606 	}
523*2d9fd380Sjfb8856606 
524*2d9fd380Sjfb8856606 	/* Connect last stage worker nodes to sink nodes */
525*2d9fd380Sjfb8856606 	for (i = 0; i < nodes_per_stage; i++) {
526*2d9fd380Sjfb8856606 		edges = 0;
527*2d9fd380Sjfb8856606 		total_percent = 0;
528*2d9fd380Sjfb8856606 		node_data = graph_get_node_data(graph_data,
529*2d9fd380Sjfb8856606 						node_map[stages - 1][i]);
530*2d9fd380Sjfb8856606 		/* Prepare list of sink nodes to connect to */
531*2d9fd380Sjfb8856606 		for (j = 0; j < nb_sinks; j++) {
532*2d9fd380Sjfb8856606 			if (!snk_map[i][j])
533*2d9fd380Sjfb8856606 				continue;
534*2d9fd380Sjfb8856606 			ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE);
535*2d9fd380Sjfb8856606 			snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s",
536*2d9fd380Sjfb8856606 				 rte_node_id_to_name(snk_nodes[j]));
537*2d9fd380Sjfb8856606 			node_data->next_nodes[edges] = snk_nodes[j];
538*2d9fd380Sjfb8856606 			node_data->next_percentage[edges] = snk_map[i][j];
539*2d9fd380Sjfb8856606 			edges++;
540*2d9fd380Sjfb8856606 			total_percent += snk_map[i][j];
541*2d9fd380Sjfb8856606 		}
542*2d9fd380Sjfb8856606 		if (!edges)
543*2d9fd380Sjfb8856606 			continue;
544*2d9fd380Sjfb8856606 		if (edges >= MAX_EDGES_PER_NODE || total_percent != 100) {
545*2d9fd380Sjfb8856606 			printf("Invalid edge configuration\n");
546*2d9fd380Sjfb8856606 			for (j = 0; j < edges; j++)
547*2d9fd380Sjfb8856606 				free(ename[i]);
548*2d9fd380Sjfb8856606 			goto pattern_name_free;
549*2d9fd380Sjfb8856606 		}
550*2d9fd380Sjfb8856606 
551*2d9fd380Sjfb8856606 		/* Connect a worker node to a list of sink nodes */
552*2d9fd380Sjfb8856606 		count = rte_node_edge_update(node_map[stages - 1][i], 0,
553*2d9fd380Sjfb8856606 					     (const char **)(uintptr_t)ename,
554*2d9fd380Sjfb8856606 					     edges);
555*2d9fd380Sjfb8856606 		for (k = 0; k < edges; k++)
556*2d9fd380Sjfb8856606 			free(ename[k]);
557*2d9fd380Sjfb8856606 		if (count != edges) {
558*2d9fd380Sjfb8856606 			printf("Couldn't add edges %d %d\n", edges, count);
559*2d9fd380Sjfb8856606 			goto pattern_name_free;
560*2d9fd380Sjfb8856606 		}
561*2d9fd380Sjfb8856606 	}
562*2d9fd380Sjfb8856606 
563*2d9fd380Sjfb8856606 	/* Create a Graph */
564*2d9fd380Sjfb8856606 	gconf.socket_id = SOCKET_ID_ANY;
565*2d9fd380Sjfb8856606 	gconf.nb_node_patterns = graph_data->nb_nodes;
566*2d9fd380Sjfb8856606 	gconf.node_patterns = (const char **)(uintptr_t)node_patterns;
567*2d9fd380Sjfb8856606 
568*2d9fd380Sjfb8856606 	graph_id = rte_graph_create(gname, &gconf);
569*2d9fd380Sjfb8856606 	if (graph_id == RTE_GRAPH_ID_INVALID) {
570*2d9fd380Sjfb8856606 		printf("Graph creation failed with error = %d\n", rte_errno);
571*2d9fd380Sjfb8856606 		goto pattern_name_free;
572*2d9fd380Sjfb8856606 	}
573*2d9fd380Sjfb8856606 	graph_data->graph_id = graph_id;
574*2d9fd380Sjfb8856606 
575*2d9fd380Sjfb8856606 	free(node_map);
576*2d9fd380Sjfb8856606 	for (i = 0; i < graph_data->nb_nodes; i++)
577*2d9fd380Sjfb8856606 		free(node_patterns[i]);
578*2d9fd380Sjfb8856606 	free(snk_nodes);
579*2d9fd380Sjfb8856606 	free(src_nodes);
580*2d9fd380Sjfb8856606 	free(node_patterns);
581*2d9fd380Sjfb8856606 	return 0;
582*2d9fd380Sjfb8856606 
583*2d9fd380Sjfb8856606 pattern_name_free:
584*2d9fd380Sjfb8856606 	free(node_map);
585*2d9fd380Sjfb8856606 	for (i = 0; i < graph_data->nb_nodes; i++)
586*2d9fd380Sjfb8856606 		free(node_patterns[i]);
587*2d9fd380Sjfb8856606 snk_free:
588*2d9fd380Sjfb8856606 	free(snk_nodes);
589*2d9fd380Sjfb8856606 src_free:
590*2d9fd380Sjfb8856606 	free(src_nodes);
591*2d9fd380Sjfb8856606 pattern_free:
592*2d9fd380Sjfb8856606 	free(node_patterns);
593*2d9fd380Sjfb8856606 data_free:
594*2d9fd380Sjfb8856606 	free(graph_data->node_data);
595*2d9fd380Sjfb8856606 memzone_free:
596*2d9fd380Sjfb8856606 	rte_memzone_free(mz);
597*2d9fd380Sjfb8856606 	return -ENOMEM;
598*2d9fd380Sjfb8856606 }
599*2d9fd380Sjfb8856606 
600*2d9fd380Sjfb8856606 /* Worker thread function */
601*2d9fd380Sjfb8856606 static int
_graph_perf_wrapper(void * args)602*2d9fd380Sjfb8856606 _graph_perf_wrapper(void *args)
603*2d9fd380Sjfb8856606 {
604*2d9fd380Sjfb8856606 	struct graph_lcore_data *data = args;
605*2d9fd380Sjfb8856606 	struct rte_graph *graph;
606*2d9fd380Sjfb8856606 
607*2d9fd380Sjfb8856606 	/* Lookup graph */
608*2d9fd380Sjfb8856606 	graph = rte_graph_lookup(rte_graph_id_to_name(data->graph_id));
609*2d9fd380Sjfb8856606 
610*2d9fd380Sjfb8856606 	/* Graph walk until done */
611*2d9fd380Sjfb8856606 	while (!data->done)
612*2d9fd380Sjfb8856606 		rte_graph_walk(graph);
613*2d9fd380Sjfb8856606 
614*2d9fd380Sjfb8856606 	return 0;
615*2d9fd380Sjfb8856606 }
616*2d9fd380Sjfb8856606 
617*2d9fd380Sjfb8856606 static int
measure_perf_get(rte_graph_t graph_id)618*2d9fd380Sjfb8856606 measure_perf_get(rte_graph_t graph_id)
619*2d9fd380Sjfb8856606 {
620*2d9fd380Sjfb8856606 	const char *pattern = rte_graph_id_to_name(graph_id);
621*2d9fd380Sjfb8856606 	uint32_t lcore_id = rte_get_next_lcore(-1, 1, 0);
622*2d9fd380Sjfb8856606 	struct rte_graph_cluster_stats_param param;
623*2d9fd380Sjfb8856606 	struct rte_graph_cluster_stats *stats;
624*2d9fd380Sjfb8856606 	struct graph_lcore_data *data;
625*2d9fd380Sjfb8856606 
626*2d9fd380Sjfb8856606 	data = rte_zmalloc("Graph_perf", sizeof(struct graph_lcore_data),
627*2d9fd380Sjfb8856606 			   RTE_CACHE_LINE_SIZE);
628*2d9fd380Sjfb8856606 	data->graph_id = graph_id;
629*2d9fd380Sjfb8856606 	data->done = 0;
630*2d9fd380Sjfb8856606 
631*2d9fd380Sjfb8856606 	/* Run graph worker thread function */
632*2d9fd380Sjfb8856606 	rte_eal_remote_launch(_graph_perf_wrapper, data, lcore_id);
633*2d9fd380Sjfb8856606 
634*2d9fd380Sjfb8856606 	/* Collect stats for few msecs */
635*2d9fd380Sjfb8856606 	if (rte_graph_has_stats_feature()) {
636*2d9fd380Sjfb8856606 		memset(&param, 0, sizeof(param));
637*2d9fd380Sjfb8856606 		param.f = stdout;
638*2d9fd380Sjfb8856606 		param.socket_id = SOCKET_ID_ANY;
639*2d9fd380Sjfb8856606 		param.graph_patterns = &pattern;
640*2d9fd380Sjfb8856606 		param.nb_graph_patterns = 1;
641*2d9fd380Sjfb8856606 
642*2d9fd380Sjfb8856606 		stats = rte_graph_cluster_stats_create(&param);
643*2d9fd380Sjfb8856606 		if (stats == NULL) {
644*2d9fd380Sjfb8856606 			printf("Failed to create stats\n");
645*2d9fd380Sjfb8856606 			return -ENOMEM;
646*2d9fd380Sjfb8856606 		}
647*2d9fd380Sjfb8856606 
648*2d9fd380Sjfb8856606 		rte_delay_ms(3E2);
649*2d9fd380Sjfb8856606 		rte_graph_cluster_stats_get(stats, true);
650*2d9fd380Sjfb8856606 		rte_delay_ms(1E3);
651*2d9fd380Sjfb8856606 		rte_graph_cluster_stats_get(stats, false);
652*2d9fd380Sjfb8856606 		rte_graph_cluster_stats_destroy(stats);
653*2d9fd380Sjfb8856606 	} else
654*2d9fd380Sjfb8856606 		rte_delay_ms(1E3);
655*2d9fd380Sjfb8856606 
656*2d9fd380Sjfb8856606 	data->done = 1;
657*2d9fd380Sjfb8856606 	rte_eal_wait_lcore(lcore_id);
658*2d9fd380Sjfb8856606 
659*2d9fd380Sjfb8856606 	return 0;
660*2d9fd380Sjfb8856606 }
661*2d9fd380Sjfb8856606 
662*2d9fd380Sjfb8856606 static inline void
graph_fini(void)663*2d9fd380Sjfb8856606 graph_fini(void)
664*2d9fd380Sjfb8856606 {
665*2d9fd380Sjfb8856606 	const struct rte_memzone *mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ);
666*2d9fd380Sjfb8856606 	struct test_graph_perf *graph_data;
667*2d9fd380Sjfb8856606 
668*2d9fd380Sjfb8856606 	if (mz == NULL)
669*2d9fd380Sjfb8856606 		return;
670*2d9fd380Sjfb8856606 	graph_data = mz->addr;
671*2d9fd380Sjfb8856606 
672*2d9fd380Sjfb8856606 	rte_graph_destroy(graph_data->graph_id);
673*2d9fd380Sjfb8856606 	free(graph_data->node_data);
674*2d9fd380Sjfb8856606 	rte_memzone_free(rte_memzone_lookup(TEST_GRAPH_PERF_MZ));
675*2d9fd380Sjfb8856606 }
676*2d9fd380Sjfb8856606 
677*2d9fd380Sjfb8856606 static int
measure_perf(void)678*2d9fd380Sjfb8856606 measure_perf(void)
679*2d9fd380Sjfb8856606 {
680*2d9fd380Sjfb8856606 	const struct rte_memzone *mz;
681*2d9fd380Sjfb8856606 	struct test_graph_perf *graph_data;
682*2d9fd380Sjfb8856606 
683*2d9fd380Sjfb8856606 	mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ);
684*2d9fd380Sjfb8856606 	if (mz == NULL)
685*2d9fd380Sjfb8856606 		return -ENOMEM;
686*2d9fd380Sjfb8856606 	graph_data = mz->addr;
687*2d9fd380Sjfb8856606 
688*2d9fd380Sjfb8856606 	return measure_perf_get(graph_data->graph_id);
689*2d9fd380Sjfb8856606 }
690*2d9fd380Sjfb8856606 
691*2d9fd380Sjfb8856606 static inline int
graph_hr_4s_1n_1src_1snk(void)692*2d9fd380Sjfb8856606 graph_hr_4s_1n_1src_1snk(void)
693*2d9fd380Sjfb8856606 {
694*2d9fd380Sjfb8856606 	return measure_perf();
695*2d9fd380Sjfb8856606 }
696*2d9fd380Sjfb8856606 
697*2d9fd380Sjfb8856606 static inline int
graph_hr_4s_1n_1src_1snk_brst_one(void)698*2d9fd380Sjfb8856606 graph_hr_4s_1n_1src_1snk_brst_one(void)
699*2d9fd380Sjfb8856606 {
700*2d9fd380Sjfb8856606 	return measure_perf();
701*2d9fd380Sjfb8856606 }
702*2d9fd380Sjfb8856606 
703*2d9fd380Sjfb8856606 static inline int
graph_hr_4s_1n_2src_1snk(void)704*2d9fd380Sjfb8856606 graph_hr_4s_1n_2src_1snk(void)
705*2d9fd380Sjfb8856606 {
706*2d9fd380Sjfb8856606 	return measure_perf();
707*2d9fd380Sjfb8856606 }
708*2d9fd380Sjfb8856606 
709*2d9fd380Sjfb8856606 static inline int
graph_hr_4s_1n_1src_2snk(void)710*2d9fd380Sjfb8856606 graph_hr_4s_1n_1src_2snk(void)
711*2d9fd380Sjfb8856606 {
712*2d9fd380Sjfb8856606 	return measure_perf();
713*2d9fd380Sjfb8856606 }
714*2d9fd380Sjfb8856606 
715*2d9fd380Sjfb8856606 static inline int
graph_tree_4s_4n_1src_4snk(void)716*2d9fd380Sjfb8856606 graph_tree_4s_4n_1src_4snk(void)
717*2d9fd380Sjfb8856606 {
718*2d9fd380Sjfb8856606 	return measure_perf();
719*2d9fd380Sjfb8856606 }
720*2d9fd380Sjfb8856606 
721*2d9fd380Sjfb8856606 static inline int
graph_reverse_tree_3s_4n_1src_1snk(void)722*2d9fd380Sjfb8856606 graph_reverse_tree_3s_4n_1src_1snk(void)
723*2d9fd380Sjfb8856606 {
724*2d9fd380Sjfb8856606 	return measure_perf();
725*2d9fd380Sjfb8856606 }
726*2d9fd380Sjfb8856606 
727*2d9fd380Sjfb8856606 static inline int
graph_parallel_tree_5s_4n_4src_4snk(void)728*2d9fd380Sjfb8856606 graph_parallel_tree_5s_4n_4src_4snk(void)
729*2d9fd380Sjfb8856606 {
730*2d9fd380Sjfb8856606 	return measure_perf();
731*2d9fd380Sjfb8856606 }
732*2d9fd380Sjfb8856606 
733*2d9fd380Sjfb8856606 /* Graph Topology
734*2d9fd380Sjfb8856606  * nodes per stage:	1
735*2d9fd380Sjfb8856606  * stages:		4
736*2d9fd380Sjfb8856606  * src:			1
737*2d9fd380Sjfb8856606  * sink:		1
738*2d9fd380Sjfb8856606  */
739*2d9fd380Sjfb8856606 static inline int
graph_init_hr(void)740*2d9fd380Sjfb8856606 graph_init_hr(void)
741*2d9fd380Sjfb8856606 {
742*2d9fd380Sjfb8856606 	uint8_t edge_map[][1][1] = {
743*2d9fd380Sjfb8856606 		{ {100} },
744*2d9fd380Sjfb8856606 		{ {100} },
745*2d9fd380Sjfb8856606 		{ {100} },
746*2d9fd380Sjfb8856606 		{ {100} },
747*2d9fd380Sjfb8856606 	};
748*2d9fd380Sjfb8856606 	uint8_t src_map[][1] = { {100} };
749*2d9fd380Sjfb8856606 	uint8_t snk_map[][1] = { {100} };
750*2d9fd380Sjfb8856606 
751*2d9fd380Sjfb8856606 	return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map),
752*2d9fd380Sjfb8856606 			  STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
753*2d9fd380Sjfb8856606 			  snk_map, edge_map, 0);
754*2d9fd380Sjfb8856606 }
755*2d9fd380Sjfb8856606 
756*2d9fd380Sjfb8856606 /* Graph Topology
757*2d9fd380Sjfb8856606  * nodes per stage:	1
758*2d9fd380Sjfb8856606  * stages:		4
759*2d9fd380Sjfb8856606  * src:			1
760*2d9fd380Sjfb8856606  * sink:		1
761*2d9fd380Sjfb8856606  */
762*2d9fd380Sjfb8856606 static inline int
graph_init_hr_brst_one(void)763*2d9fd380Sjfb8856606 graph_init_hr_brst_one(void)
764*2d9fd380Sjfb8856606 {
765*2d9fd380Sjfb8856606 	uint8_t edge_map[][1][1] = {
766*2d9fd380Sjfb8856606 		{ {100} },
767*2d9fd380Sjfb8856606 		{ {100} },
768*2d9fd380Sjfb8856606 		{ {100} },
769*2d9fd380Sjfb8856606 		{ {100} },
770*2d9fd380Sjfb8856606 	};
771*2d9fd380Sjfb8856606 	uint8_t src_map[][1] = { {100} };
772*2d9fd380Sjfb8856606 	uint8_t snk_map[][1] = { {100} };
773*2d9fd380Sjfb8856606 
774*2d9fd380Sjfb8856606 	return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map),
775*2d9fd380Sjfb8856606 			  STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
776*2d9fd380Sjfb8856606 			  snk_map, edge_map, 1);
777*2d9fd380Sjfb8856606 }
778*2d9fd380Sjfb8856606 
779*2d9fd380Sjfb8856606 /* Graph Topology
780*2d9fd380Sjfb8856606  * nodes per stage:	1
781*2d9fd380Sjfb8856606  * stages:		4
782*2d9fd380Sjfb8856606  * src:			2
783*2d9fd380Sjfb8856606  * sink:		1
784*2d9fd380Sjfb8856606  */
785*2d9fd380Sjfb8856606 static inline int
graph_init_hr_multi_src(void)786*2d9fd380Sjfb8856606 graph_init_hr_multi_src(void)
787*2d9fd380Sjfb8856606 {
788*2d9fd380Sjfb8856606 	uint8_t edge_map[][1][1] = {
789*2d9fd380Sjfb8856606 		{ {100} },
790*2d9fd380Sjfb8856606 		{ {100} },
791*2d9fd380Sjfb8856606 		{ {100} },
792*2d9fd380Sjfb8856606 		{ {100} },
793*2d9fd380Sjfb8856606 	};
794*2d9fd380Sjfb8856606 	uint8_t src_map[][1] = {
795*2d9fd380Sjfb8856606 		{100}, {100}
796*2d9fd380Sjfb8856606 	};
797*2d9fd380Sjfb8856606 	uint8_t snk_map[][1] = { {100} };
798*2d9fd380Sjfb8856606 
799*2d9fd380Sjfb8856606 	return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map),
800*2d9fd380Sjfb8856606 			  STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
801*2d9fd380Sjfb8856606 			  snk_map, edge_map, 0);
802*2d9fd380Sjfb8856606 }
803*2d9fd380Sjfb8856606 
804*2d9fd380Sjfb8856606 /* Graph Topology
805*2d9fd380Sjfb8856606  * nodes per stage:	1
806*2d9fd380Sjfb8856606  * stages:		4
807*2d9fd380Sjfb8856606  * src:			1
808*2d9fd380Sjfb8856606  * sink:		2
809*2d9fd380Sjfb8856606  */
810*2d9fd380Sjfb8856606 static inline int
graph_init_hr_multi_snk(void)811*2d9fd380Sjfb8856606 graph_init_hr_multi_snk(void)
812*2d9fd380Sjfb8856606 {
813*2d9fd380Sjfb8856606 	uint8_t edge_map[][1][1] = {
814*2d9fd380Sjfb8856606 		{ {100} },
815*2d9fd380Sjfb8856606 		{ {100} },
816*2d9fd380Sjfb8856606 		{ {100} },
817*2d9fd380Sjfb8856606 		{ {100} },
818*2d9fd380Sjfb8856606 	};
819*2d9fd380Sjfb8856606 	uint8_t src_map[][1] = { {100} };
820*2d9fd380Sjfb8856606 	uint8_t snk_map[][2] = { {50, 50} };
821*2d9fd380Sjfb8856606 
822*2d9fd380Sjfb8856606 	return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map),
823*2d9fd380Sjfb8856606 			  STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
824*2d9fd380Sjfb8856606 			  snk_map, edge_map, 0);
825*2d9fd380Sjfb8856606 }
826*2d9fd380Sjfb8856606 
827*2d9fd380Sjfb8856606 /* Graph Topology
828*2d9fd380Sjfb8856606  * nodes per stage:	4
829*2d9fd380Sjfb8856606  * stages:		4
830*2d9fd380Sjfb8856606  * src:			1
831*2d9fd380Sjfb8856606  * sink:		4
832*2d9fd380Sjfb8856606  */
833*2d9fd380Sjfb8856606 static inline int
graph_init_tree(void)834*2d9fd380Sjfb8856606 graph_init_tree(void)
835*2d9fd380Sjfb8856606 {
836*2d9fd380Sjfb8856606 	uint8_t edge_map[][4][4] = {
837*2d9fd380Sjfb8856606 		{
838*2d9fd380Sjfb8856606 			{100, 0, 0, 0},
839*2d9fd380Sjfb8856606 			{0, 0, 0, 0},
840*2d9fd380Sjfb8856606 			{0, 0, 0, 0},
841*2d9fd380Sjfb8856606 			{0, 0, 0, 0}
842*2d9fd380Sjfb8856606 		},
843*2d9fd380Sjfb8856606 		{
844*2d9fd380Sjfb8856606 			{50, 0, 0, 0},
845*2d9fd380Sjfb8856606 			{50, 0, 0, 0},
846*2d9fd380Sjfb8856606 			{0, 0, 0, 0},
847*2d9fd380Sjfb8856606 			{0, 0, 0, 0}
848*2d9fd380Sjfb8856606 		},
849*2d9fd380Sjfb8856606 		{
850*2d9fd380Sjfb8856606 			{33, 33, 0, 0},
851*2d9fd380Sjfb8856606 			{34, 34, 0, 0},
852*2d9fd380Sjfb8856606 			{33, 33, 0, 0},
853*2d9fd380Sjfb8856606 			{0, 0, 0, 0}
854*2d9fd380Sjfb8856606 		},
855*2d9fd380Sjfb8856606 		{
856*2d9fd380Sjfb8856606 			{25, 25, 25, 0},
857*2d9fd380Sjfb8856606 			{25, 25, 25, 0},
858*2d9fd380Sjfb8856606 			{25, 25, 25, 0},
859*2d9fd380Sjfb8856606 			{25, 25, 25, 0}
860*2d9fd380Sjfb8856606 		}
861*2d9fd380Sjfb8856606 	};
862*2d9fd380Sjfb8856606 	uint8_t src_map[][4] = { {100, 0, 0, 0} };
863*2d9fd380Sjfb8856606 	uint8_t snk_map[][4] = {
864*2d9fd380Sjfb8856606 		{100, 0, 0, 0},
865*2d9fd380Sjfb8856606 		{0, 100, 0, 0},
866*2d9fd380Sjfb8856606 		{0, 0, 100, 0},
867*2d9fd380Sjfb8856606 		{0, 0, 0, 100}
868*2d9fd380Sjfb8856606 	};
869*2d9fd380Sjfb8856606 
870*2d9fd380Sjfb8856606 	return graph_init("graph_full_split", SOURCES(src_map), SINKS(snk_map),
871*2d9fd380Sjfb8856606 			  STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
872*2d9fd380Sjfb8856606 			  snk_map, edge_map, 0);
873*2d9fd380Sjfb8856606 }
874*2d9fd380Sjfb8856606 
875*2d9fd380Sjfb8856606 /* Graph Topology
876*2d9fd380Sjfb8856606  * nodes per stage:	4
877*2d9fd380Sjfb8856606  * stages:		3
878*2d9fd380Sjfb8856606  * src:			1
879*2d9fd380Sjfb8856606  * sink:		1
880*2d9fd380Sjfb8856606  */
881*2d9fd380Sjfb8856606 static inline int
graph_init_reverse_tree(void)882*2d9fd380Sjfb8856606 graph_init_reverse_tree(void)
883*2d9fd380Sjfb8856606 {
884*2d9fd380Sjfb8856606 	uint8_t edge_map[][4][4] = {
885*2d9fd380Sjfb8856606 		{
886*2d9fd380Sjfb8856606 			{25, 25, 25, 25},
887*2d9fd380Sjfb8856606 			{25, 25, 25, 25},
888*2d9fd380Sjfb8856606 			{25, 25, 25, 25},
889*2d9fd380Sjfb8856606 			{25, 25, 25, 25}
890*2d9fd380Sjfb8856606 		},
891*2d9fd380Sjfb8856606 		{
892*2d9fd380Sjfb8856606 			{33, 33, 33, 33},
893*2d9fd380Sjfb8856606 			{33, 33, 33, 33},
894*2d9fd380Sjfb8856606 			{34, 34, 34, 34},
895*2d9fd380Sjfb8856606 			{0, 0, 0, 0}
896*2d9fd380Sjfb8856606 		},
897*2d9fd380Sjfb8856606 		{
898*2d9fd380Sjfb8856606 			{50, 50, 50, 0},
899*2d9fd380Sjfb8856606 			{50, 50, 50, 0},
900*2d9fd380Sjfb8856606 			{0, 0, 0, 0},
901*2d9fd380Sjfb8856606 			{0, 0, 0, 0}
902*2d9fd380Sjfb8856606 		},
903*2d9fd380Sjfb8856606 	};
904*2d9fd380Sjfb8856606 	uint8_t src_map[][4] = { {25, 25, 25, 25} };
905*2d9fd380Sjfb8856606 	uint8_t snk_map[][1] = { {100}, {100}, {0}, {0} };
906*2d9fd380Sjfb8856606 
907*2d9fd380Sjfb8856606 	return graph_init("graph_full_split", SOURCES(src_map), SINKS(snk_map),
908*2d9fd380Sjfb8856606 			  STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
909*2d9fd380Sjfb8856606 			  snk_map, edge_map, 0);
910*2d9fd380Sjfb8856606 }
911*2d9fd380Sjfb8856606 
912*2d9fd380Sjfb8856606 /* Graph Topology
913*2d9fd380Sjfb8856606  * nodes per stage:	4
914*2d9fd380Sjfb8856606  * stages:		5
915*2d9fd380Sjfb8856606  * src:			4
916*2d9fd380Sjfb8856606  * sink:		4
917*2d9fd380Sjfb8856606  */
918*2d9fd380Sjfb8856606 static inline int
graph_init_parallel_tree(void)919*2d9fd380Sjfb8856606 graph_init_parallel_tree(void)
920*2d9fd380Sjfb8856606 {
921*2d9fd380Sjfb8856606 	uint8_t edge_map[][4][4] = {
922*2d9fd380Sjfb8856606 		{
923*2d9fd380Sjfb8856606 			{100, 0, 0, 0},
924*2d9fd380Sjfb8856606 			{0, 100, 0, 0},
925*2d9fd380Sjfb8856606 			{0, 0, 100, 0},
926*2d9fd380Sjfb8856606 			{0, 0, 0, 100}
927*2d9fd380Sjfb8856606 		},
928*2d9fd380Sjfb8856606 		{
929*2d9fd380Sjfb8856606 			{100, 0, 0, 0},
930*2d9fd380Sjfb8856606 			{0, 100, 0, 0},
931*2d9fd380Sjfb8856606 			{0, 0, 100, 0},
932*2d9fd380Sjfb8856606 			{0, 0, 0, 100}
933*2d9fd380Sjfb8856606 		},
934*2d9fd380Sjfb8856606 		{
935*2d9fd380Sjfb8856606 			{100, 0, 0, 0},
936*2d9fd380Sjfb8856606 			{0, 100, 0, 0},
937*2d9fd380Sjfb8856606 			{0, 0, 100, 0},
938*2d9fd380Sjfb8856606 			{0, 0, 0, 100}
939*2d9fd380Sjfb8856606 		},
940*2d9fd380Sjfb8856606 		{
941*2d9fd380Sjfb8856606 			{100, 0, 0, 0},
942*2d9fd380Sjfb8856606 			{0, 100, 0, 0},
943*2d9fd380Sjfb8856606 			{0, 0, 100, 0},
944*2d9fd380Sjfb8856606 			{0, 0, 0, 100}
945*2d9fd380Sjfb8856606 		},
946*2d9fd380Sjfb8856606 		{
947*2d9fd380Sjfb8856606 			{100, 0, 0, 0},
948*2d9fd380Sjfb8856606 			{0, 100, 0, 0},
949*2d9fd380Sjfb8856606 			{0, 0, 100, 0},
950*2d9fd380Sjfb8856606 			{0, 0, 0, 100}
951*2d9fd380Sjfb8856606 		},
952*2d9fd380Sjfb8856606 	};
953*2d9fd380Sjfb8856606 	uint8_t src_map[][4] = {
954*2d9fd380Sjfb8856606 		{100, 0, 0, 0},
955*2d9fd380Sjfb8856606 		{0, 100, 0, 0},
956*2d9fd380Sjfb8856606 		{0, 0, 100, 0},
957*2d9fd380Sjfb8856606 		{0, 0, 0, 100}
958*2d9fd380Sjfb8856606 	};
959*2d9fd380Sjfb8856606 	uint8_t snk_map[][4] = {
960*2d9fd380Sjfb8856606 		{100, 0, 0, 0},
961*2d9fd380Sjfb8856606 		{0, 100, 0, 0},
962*2d9fd380Sjfb8856606 		{0, 0, 100, 0},
963*2d9fd380Sjfb8856606 		{0, 0, 0, 100}
964*2d9fd380Sjfb8856606 	};
965*2d9fd380Sjfb8856606 
966*2d9fd380Sjfb8856606 	return graph_init("graph_parallel", SOURCES(src_map), SINKS(snk_map),
967*2d9fd380Sjfb8856606 			  STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
968*2d9fd380Sjfb8856606 			  snk_map, edge_map, 0);
969*2d9fd380Sjfb8856606 }
970*2d9fd380Sjfb8856606 
971*2d9fd380Sjfb8856606 /** Graph Creation cheat sheet
972*2d9fd380Sjfb8856606  *  edge_map -> dictates graph flow from worker stage 0 to worker stage n-1.
973*2d9fd380Sjfb8856606  *  src_map  -> dictates source nodes enqueue percentage to worker stage 0.
974*2d9fd380Sjfb8856606  *  snk_map  -> dictates stage n-1 enqueue percentage to sink.
975*2d9fd380Sjfb8856606  *
976*2d9fd380Sjfb8856606  *  Layout:
977*2d9fd380Sjfb8856606  *  edge_map[<nb_stages>][<nodes_per_stg>][<nodes_in_nxt_stg = nodes_per_stg>]
978*2d9fd380Sjfb8856606  *  src_map[<nb_sources>][<nodes_in_stage0 = nodes_per_stage>]
979*2d9fd380Sjfb8856606  *  snk_map[<nodes_in_stage(n-1) = nodes_per_stage>][<nb_sinks>]
980*2d9fd380Sjfb8856606  *
981*2d9fd380Sjfb8856606  *  The last array dictates the percentage of received objs to enqueue to next
982*2d9fd380Sjfb8856606  *  stage.
983*2d9fd380Sjfb8856606  *
984*2d9fd380Sjfb8856606  *  Note: edge_map[][0][] will always be unused as it will receive from source
985*2d9fd380Sjfb8856606  *
986*2d9fd380Sjfb8856606  *  Example:
987*2d9fd380Sjfb8856606  *	Graph:
988*2d9fd380Sjfb8856606  *	http://bit.ly/2PqbqOy
989*2d9fd380Sjfb8856606  *	Each stage(n) connects to all nodes in the next stage in decreasing
990*2d9fd380Sjfb8856606  *	order.
991*2d9fd380Sjfb8856606  *	Since we can't resize the edge_map dynamically we get away by creating
992*2d9fd380Sjfb8856606  *	dummy nodes and assigning 0 percentages.
993*2d9fd380Sjfb8856606  *	Max nodes across all stages = 4
994*2d9fd380Sjfb8856606  *	stages = 3
995*2d9fd380Sjfb8856606  *	nb_src = 1
996*2d9fd380Sjfb8856606  *	nb_snk = 1
997*2d9fd380Sjfb8856606  *			   // Stages
998*2d9fd380Sjfb8856606  *	edge_map[][4][4] = {
999*2d9fd380Sjfb8856606  *		// Nodes per stage
1000*2d9fd380Sjfb8856606  *		{
1001*2d9fd380Sjfb8856606  *		    {25, 25, 25, 25},
1002*2d9fd380Sjfb8856606  *		    {25, 25, 25, 25},
1003*2d9fd380Sjfb8856606  *		    {25, 25, 25, 25},
1004*2d9fd380Sjfb8856606  *		    {25, 25, 25, 25}
1005*2d9fd380Sjfb8856606  *		},	// This will be unused.
1006*2d9fd380Sjfb8856606  *		{
1007*2d9fd380Sjfb8856606  *		    // Nodes enabled in current stage + prev stage enq %
1008*2d9fd380Sjfb8856606  *		    {33, 33, 33, 33},
1009*2d9fd380Sjfb8856606  *		    {33, 33, 33, 33},
1010*2d9fd380Sjfb8856606  *		    {34, 34, 34, 34},
1011*2d9fd380Sjfb8856606  *		    {0, 0, 0, 0}
1012*2d9fd380Sjfb8856606  *		},
1013*2d9fd380Sjfb8856606  *		{
1014*2d9fd380Sjfb8856606  *		    {50, 50, 50, 0},
1015*2d9fd380Sjfb8856606  *		    {50, 50, 50, 0},
1016*2d9fd380Sjfb8856606  *		    {0, 0, 0, 0},
1017*2d9fd380Sjfb8856606  *		    {0, 0, 0, 0}
1018*2d9fd380Sjfb8856606  *		},
1019*2d9fd380Sjfb8856606  *	};
1020*2d9fd380Sjfb8856606  *	Above, each stage tells how much it should receive from previous except
1021*2d9fd380Sjfb8856606  *	from stage_0.
1022*2d9fd380Sjfb8856606  *
1023*2d9fd380Sjfb8856606  *	src_map[][4] = { {25, 25, 25, 25} };
1024*2d9fd380Sjfb8856606  *	Here, we tell each source the % it has to send to stage_0 nodes. In
1025*2d9fd380Sjfb8856606  *	case we want 2 source node we can declare as
1026*2d9fd380Sjfb8856606  *	src_map[][4] = { {25, 25, 25, 25}, {25, 25, 25, 25} };
1027*2d9fd380Sjfb8856606  *
1028*2d9fd380Sjfb8856606  *	snk_map[][1] = { {100}, {100}, {0}, {0} }
1029*2d9fd380Sjfb8856606  *	Here, we tell stage - 1 nodes how much to enqueue to sink_0.
1030*2d9fd380Sjfb8856606  *	If we have 2 sinks we can do as follows
1031*2d9fd380Sjfb8856606  *	snk_map[][2] = { {50, 50}, {50, 50}, {0, 0}, {0, 0} }
1032*2d9fd380Sjfb8856606  */
1033*2d9fd380Sjfb8856606 
1034*2d9fd380Sjfb8856606 static struct unit_test_suite graph_perf_testsuite = {
1035*2d9fd380Sjfb8856606 	.suite_name = "Graph library performance test suite",
1036*2d9fd380Sjfb8856606 	.setup = graph_perf_setup,
1037*2d9fd380Sjfb8856606 	.teardown = graph_perf_teardown,
1038*2d9fd380Sjfb8856606 	.unit_test_cases = {
1039*2d9fd380Sjfb8856606 		TEST_CASE_ST(graph_init_hr, graph_fini,
1040*2d9fd380Sjfb8856606 			     graph_hr_4s_1n_1src_1snk),
1041*2d9fd380Sjfb8856606 		TEST_CASE_ST(graph_init_hr_brst_one, graph_fini,
1042*2d9fd380Sjfb8856606 			     graph_hr_4s_1n_1src_1snk_brst_one),
1043*2d9fd380Sjfb8856606 		TEST_CASE_ST(graph_init_hr_multi_src, graph_fini,
1044*2d9fd380Sjfb8856606 			     graph_hr_4s_1n_2src_1snk),
1045*2d9fd380Sjfb8856606 		TEST_CASE_ST(graph_init_hr_multi_snk, graph_fini,
1046*2d9fd380Sjfb8856606 			     graph_hr_4s_1n_1src_2snk),
1047*2d9fd380Sjfb8856606 		TEST_CASE_ST(graph_init_tree, graph_fini,
1048*2d9fd380Sjfb8856606 			     graph_tree_4s_4n_1src_4snk),
1049*2d9fd380Sjfb8856606 		TEST_CASE_ST(graph_init_reverse_tree, graph_fini,
1050*2d9fd380Sjfb8856606 			     graph_reverse_tree_3s_4n_1src_1snk),
1051*2d9fd380Sjfb8856606 		TEST_CASE_ST(graph_init_parallel_tree, graph_fini,
1052*2d9fd380Sjfb8856606 			     graph_parallel_tree_5s_4n_4src_4snk),
1053*2d9fd380Sjfb8856606 		TEST_CASES_END(), /**< NULL terminate unit test array */
1054*2d9fd380Sjfb8856606 	},
1055*2d9fd380Sjfb8856606 };
1056*2d9fd380Sjfb8856606 
1057*2d9fd380Sjfb8856606 static int
test_graph_perf_func(void)1058*2d9fd380Sjfb8856606 test_graph_perf_func(void)
1059*2d9fd380Sjfb8856606 {
1060*2d9fd380Sjfb8856606 	return unit_test_suite_runner(&graph_perf_testsuite);
1061*2d9fd380Sjfb8856606 }
1062*2d9fd380Sjfb8856606 
1063*2d9fd380Sjfb8856606 REGISTER_TEST_COMMAND(graph_perf_autotest, test_graph_perf_func);
1064