1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2020 Marvell International Ltd.
3 */
4 #include <assert.h>
5 #include <inttypes.h>
6 #include <signal.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 #include <rte_errno.h>
12 #include <rte_graph.h>
13 #include <rte_graph_worker.h>
14 #include <rte_mbuf.h>
15 #include <rte_mbuf_dyn.h>
16 #include <rte_random.h>
17
18 #include "test.h"
19
20 static uint16_t test_node_worker_source(struct rte_graph *graph,
21 struct rte_node *node, void **objs,
22 uint16_t nb_objs);
23
24 static uint16_t test_node0_worker(struct rte_graph *graph,
25 struct rte_node *node, void **objs,
26 uint16_t nb_objs);
27
28 static uint16_t test_node1_worker(struct rte_graph *graph,
29 struct rte_node *node, void **objs,
30 uint16_t nb_objs);
31
32 static uint16_t test_node2_worker(struct rte_graph *graph,
33 struct rte_node *node, void **objs,
34 uint16_t nb_objs);
35
36 static uint16_t test_node3_worker(struct rte_graph *graph,
37 struct rte_node *node, void **objs,
38 uint16_t nb_objs);
39
40 #define MBUFF_SIZE 512
41 #define MAX_NODES 4
42
43 typedef uint64_t graph_dynfield_t;
44 static int graph_dynfield_offset = -1;
45
46 static inline graph_dynfield_t *
graph_field(struct rte_mbuf * mbuf)47 graph_field(struct rte_mbuf *mbuf)
48 {
49 return RTE_MBUF_DYNFIELD(mbuf, \
50 graph_dynfield_offset, graph_dynfield_t *);
51 }
52
53 static struct rte_mbuf mbuf[MAX_NODES + 1][MBUFF_SIZE];
54 static void *mbuf_p[MAX_NODES + 1][MBUFF_SIZE];
55 static rte_graph_t graph_id;
56 static uint64_t obj_stats[MAX_NODES + 1];
57 static uint64_t fn_calls[MAX_NODES + 1];
58
59 const char *node_patterns[] = {
60 "test_node_source1", "test_node00",
61 "test_node00-test_node11", "test_node00-test_node22",
62 "test_node00-test_node33",
63 };
64
65 const char *node_names[] = {
66 "test_node00",
67 "test_node00-test_node11",
68 "test_node00-test_node22",
69 "test_node00-test_node33",
70 };
71
72 struct test_node_register {
73 char name[RTE_NODE_NAMESIZE];
74 rte_node_process_t process;
75 uint16_t nb_edges;
76 const char *next_nodes[MAX_NODES];
77 };
78
79 typedef struct {
80 uint32_t idx;
81 struct test_node_register node;
82 } test_node_t;
83
84 typedef struct {
85 test_node_t test_node[MAX_NODES];
86 } test_main_t;
87
88 static test_main_t test_main = {
89 .test_node = {
90 {
91 .node = {
92 .name = "test_node00",
93 .process = test_node0_worker,
94 .nb_edges = 2,
95 .next_nodes = {"test_node00-"
96 "test_node11",
97 "test_node00-"
98 "test_node22"},
99 },
100 },
101 {
102 .node = {
103 .name = "test_node11",
104 .process = test_node1_worker,
105 .nb_edges = 1,
106 .next_nodes = {"test_node00-"
107 "test_node22"},
108 },
109 },
110 {
111 .node = {
112 .name = "test_node22",
113 .process = test_node2_worker,
114 .nb_edges = 1,
115 .next_nodes = {"test_node00-"
116 "test_node33"},
117 },
118 },
119 {
120 .node = {
121 .name = "test_node33",
122 .process = test_node3_worker,
123 .nb_edges = 1,
124 .next_nodes = {"test_node00"},
125 },
126 },
127 },
128 };
129
130 static int
node_init(const struct rte_graph * graph,struct rte_node * node)131 node_init(const struct rte_graph *graph, struct rte_node *node)
132 {
133 RTE_SET_USED(graph);
134 *(uint32_t *)node->ctx = node->id;
135
136 return 0;
137 }
138
139 static struct rte_node_register test_node_source = {
140 .name = "test_node_source1",
141 .process = test_node_worker_source,
142 .flags = RTE_NODE_SOURCE_F,
143 .nb_edges = 2,
144 .init = node_init,
145 .next_nodes = {"test_node00", "test_node00-test_node11"},
146 };
147 RTE_NODE_REGISTER(test_node_source);
148
149 static struct rte_node_register test_node0 = {
150 .name = "test_node00",
151 .process = test_node0_worker,
152 .init = node_init,
153 };
154 RTE_NODE_REGISTER(test_node0);
155
156 uint16_t
test_node_worker_source(struct rte_graph * graph,struct rte_node * node,void ** objs,uint16_t nb_objs)157 test_node_worker_source(struct rte_graph *graph, struct rte_node *node,
158 void **objs, uint16_t nb_objs)
159 {
160 uint32_t obj_node0 = rte_rand() % 100, obj_node1;
161 test_main_t *tm = &test_main;
162 struct rte_mbuf *data;
163 void **next_stream;
164 rte_node_t next;
165 uint32_t i;
166
167 RTE_SET_USED(objs);
168 nb_objs = RTE_GRAPH_BURST_SIZE;
169
170 /* Prepare stream for next node 0 */
171 obj_node0 = nb_objs * obj_node0 * 0.01;
172 next = 0;
173 next_stream = rte_node_next_stream_get(graph, node, next, obj_node0);
174 for (i = 0; i < obj_node0; i++) {
175 data = &mbuf[0][i];
176 *graph_field(data) = ((uint64_t)tm->test_node[0].idx << 32) | i;
177 if ((i + 1) == obj_node0)
178 *graph_field(data) |= (1 << 16);
179 next_stream[i] = &mbuf[0][i];
180 }
181 rte_node_next_stream_put(graph, node, next, obj_node0);
182
183 /* Prepare stream for next node 1 */
184 obj_node1 = nb_objs - obj_node0;
185 next = 1;
186 next_stream = rte_node_next_stream_get(graph, node, next, obj_node1);
187 for (i = 0; i < obj_node1; i++) {
188 data = &mbuf[0][obj_node0 + i];
189 *graph_field(data) = ((uint64_t)tm->test_node[1].idx << 32) | i;
190 if ((i + 1) == obj_node1)
191 *graph_field(data) |= (1 << 16);
192 next_stream[i] = &mbuf[0][obj_node0 + i];
193 }
194
195 rte_node_next_stream_put(graph, node, next, obj_node1);
196 obj_stats[0] += nb_objs;
197 fn_calls[0] += 1;
198 return nb_objs;
199 }
200
201 uint16_t
test_node0_worker(struct rte_graph * graph,struct rte_node * node,void ** objs,uint16_t nb_objs)202 test_node0_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
203 uint16_t nb_objs)
204 {
205 test_main_t *tm = &test_main;
206
207 if (*(uint32_t *)node->ctx == test_node0.id) {
208 uint32_t obj_node0 = rte_rand() % 100, obj_node1;
209 struct rte_mbuf *data;
210 uint8_t second_pass = 0;
211 uint32_t count = 0;
212 uint32_t i;
213
214 obj_stats[1] += nb_objs;
215 fn_calls[1] += 1;
216
217 for (i = 0; i < nb_objs; i++) {
218 data = (struct rte_mbuf *)objs[i];
219 if ((*graph_field(data) >> 32) != tm->test_node[0].idx) {
220 printf("Data idx miss match at node 0, expected"
221 " = %u got = %u\n",
222 tm->test_node[0].idx,
223 (uint32_t)(*graph_field(data) >> 32));
224 goto end;
225 }
226
227 if ((*graph_field(data) & 0xffff) != (i - count)) {
228 printf("Expected buff count miss match at "
229 "node 0\n");
230 goto end;
231 }
232
233 if (*graph_field(data) & (0x1 << 16))
234 count = i + 1;
235 if (*graph_field(data) & (0x1 << 17))
236 second_pass = 1;
237 }
238
239 if (count != i) {
240 printf("Count mismatch at node 0\n");
241 goto end;
242 }
243
244 obj_node0 = nb_objs * obj_node0 * 0.01;
245 for (i = 0; i < obj_node0; i++) {
246 data = &mbuf[1][i];
247 *graph_field(data) =
248 ((uint64_t)tm->test_node[1].idx << 32) | i;
249 if ((i + 1) == obj_node0)
250 *graph_field(data) |= (1 << 16);
251 if (second_pass)
252 *graph_field(data) |= (1 << 17);
253 }
254 rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[1][0],
255 obj_node0);
256
257 obj_node1 = nb_objs - obj_node0;
258 for (i = 0; i < obj_node1; i++) {
259 data = &mbuf[1][obj_node0 + i];
260 *graph_field(data) =
261 ((uint64_t)tm->test_node[2].idx << 32) | i;
262 if ((i + 1) == obj_node1)
263 *graph_field(data) |= (1 << 16);
264 if (second_pass)
265 *graph_field(data) |= (1 << 17);
266 }
267 rte_node_enqueue(graph, node, 1, (void **)&mbuf_p[1][obj_node0],
268 obj_node1);
269
270 } else if (*(uint32_t *)node->ctx == tm->test_node[1].idx) {
271 test_node1_worker(graph, node, objs, nb_objs);
272 } else if (*(uint32_t *)node->ctx == tm->test_node[2].idx) {
273 test_node2_worker(graph, node, objs, nb_objs);
274 } else if (*(uint32_t *)node->ctx == tm->test_node[3].idx) {
275 test_node3_worker(graph, node, objs, nb_objs);
276 } else {
277 printf("Unexpected node context\n");
278 }
279
280 end:
281 return nb_objs;
282 }
283
284 uint16_t
test_node1_worker(struct rte_graph * graph,struct rte_node * node,void ** objs,uint16_t nb_objs)285 test_node1_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
286 uint16_t nb_objs)
287 {
288 test_main_t *tm = &test_main;
289 uint8_t second_pass = 0;
290 uint32_t obj_node0 = 0;
291 struct rte_mbuf *data;
292 uint32_t count = 0;
293 uint32_t i;
294
295 obj_stats[2] += nb_objs;
296 fn_calls[2] += 1;
297 for (i = 0; i < nb_objs; i++) {
298 data = (struct rte_mbuf *)objs[i];
299 if ((*graph_field(data) >> 32) != tm->test_node[1].idx) {
300 printf("Data idx miss match at node 1, expected = %u"
301 " got = %u\n",
302 tm->test_node[1].idx,
303 (uint32_t)(*graph_field(data) >> 32));
304 goto end;
305 }
306
307 if ((*graph_field(data) & 0xffff) != (i - count)) {
308 printf("Expected buff count miss match at node 1\n");
309 goto end;
310 }
311
312 if (*graph_field(data) & (0x1 << 16))
313 count = i + 1;
314 if (*graph_field(data) & (0x1 << 17))
315 second_pass = 1;
316 }
317
318 if (count != i) {
319 printf("Count mismatch at node 1\n");
320 goto end;
321 }
322
323 obj_node0 = nb_objs;
324 for (i = 0; i < obj_node0; i++) {
325 data = &mbuf[2][i];
326 *graph_field(data) = ((uint64_t)tm->test_node[2].idx << 32) | i;
327 if ((i + 1) == obj_node0)
328 *graph_field(data) |= (1 << 16);
329 if (second_pass)
330 *graph_field(data) |= (1 << 17);
331 }
332 rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[2][0], obj_node0);
333
334 end:
335 return nb_objs;
336 }
337
338 uint16_t
test_node2_worker(struct rte_graph * graph,struct rte_node * node,void ** objs,uint16_t nb_objs)339 test_node2_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
340 uint16_t nb_objs)
341 {
342 test_main_t *tm = &test_main;
343 uint8_t second_pass = 0;
344 struct rte_mbuf *data;
345 uint32_t count = 0;
346 uint32_t obj_node0;
347 uint32_t i;
348
349 obj_stats[3] += nb_objs;
350 fn_calls[3] += 1;
351 for (i = 0; i < nb_objs; i++) {
352 data = (struct rte_mbuf *)objs[i];
353 if ((*graph_field(data) >> 32) != tm->test_node[2].idx) {
354 printf("Data idx miss match at node 2, expected = %u"
355 " got = %u\n",
356 tm->test_node[2].idx,
357 (uint32_t)(*graph_field(data) >> 32));
358 goto end;
359 }
360
361 if ((*graph_field(data) & 0xffff) != (i - count)) {
362 printf("Expected buff count miss match at node 2\n");
363 goto end;
364 }
365
366 if (*graph_field(data) & (0x1 << 16))
367 count = i + 1;
368 if (*graph_field(data) & (0x1 << 17))
369 second_pass = 1;
370 }
371
372 if (count != i) {
373 printf("Count mismatch at node 2\n");
374 goto end;
375 }
376
377 if (!second_pass) {
378 obj_node0 = nb_objs;
379 for (i = 0; i < obj_node0; i++) {
380 data = &mbuf[3][i];
381 *graph_field(data) =
382 ((uint64_t)tm->test_node[3].idx << 32) | i;
383 if ((i + 1) == obj_node0)
384 *graph_field(data) |= (1 << 16);
385 }
386 rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[3][0],
387 obj_node0);
388 }
389
390 end:
391 return nb_objs;
392 }
393
394 uint16_t
test_node3_worker(struct rte_graph * graph,struct rte_node * node,void ** objs,uint16_t nb_objs)395 test_node3_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
396 uint16_t nb_objs)
397 {
398 test_main_t *tm = &test_main;
399 uint8_t second_pass = 0;
400 struct rte_mbuf *data;
401 uint32_t count = 0;
402 uint32_t obj_node0;
403 uint32_t i;
404
405 obj_stats[4] += nb_objs;
406 fn_calls[4] += 1;
407 for (i = 0; i < nb_objs; i++) {
408 data = (struct rte_mbuf *)objs[i];
409 if ((*graph_field(data) >> 32) != tm->test_node[3].idx) {
410 printf("Data idx miss match at node 3, expected = %u"
411 " got = %u\n",
412 tm->test_node[3].idx,
413 (uint32_t)(*graph_field(data) >> 32));
414 goto end;
415 }
416
417 if ((*graph_field(data) & 0xffff) != (i - count)) {
418 printf("Expected buff count miss match at node 3\n");
419 goto end;
420 }
421
422 if (*graph_field(data) & (0x1 << 16))
423 count = i + 1;
424 if (*graph_field(data) & (0x1 << 17))
425 second_pass = 1;
426 }
427
428 if (count != i) {
429 printf("Count mismatch at node 3\n");
430 goto end;
431 }
432
433 if (second_pass) {
434 printf("Unexpected buffers are at node 3\n");
435 goto end;
436 } else {
437 obj_node0 = nb_objs * 2;
438 for (i = 0; i < obj_node0; i++) {
439 data = &mbuf[4][i];
440 *graph_field(data) =
441 ((uint64_t)tm->test_node[0].idx << 32) | i;
442 *graph_field(data) |= (1 << 17);
443 if ((i + 1) == obj_node0)
444 *graph_field(data) |= (1 << 16);
445 }
446 rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[4][0],
447 obj_node0);
448 }
449
450 end:
451 return nb_objs;
452 }
453
454 static int
test_lookup_functions(void)455 test_lookup_functions(void)
456 {
457 test_main_t *tm = &test_main;
458 int i;
459
460 /* Verify the name with ID */
461 for (i = 1; i < MAX_NODES; i++) {
462 char *name = rte_node_id_to_name(tm->test_node[i].idx);
463 if (strcmp(name, node_names[i]) != 0) {
464 printf("Test node name verify by ID = %d failed "
465 "Expected = %s, got %s\n",
466 i, node_names[i], name);
467 return -1;
468 }
469 }
470
471 /* Verify by name */
472 for (i = 1; i < MAX_NODES; i++) {
473 uint32_t idx = rte_node_from_name(node_names[i]);
474 if (idx != tm->test_node[i].idx) {
475 printf("Test node ID verify by name = %s failed "
476 "Expected = %d, got %d\n",
477 node_names[i], tm->test_node[i].idx, idx);
478 return -1;
479 }
480 }
481
482 /* Verify edge count */
483 for (i = 1; i < MAX_NODES; i++) {
484 uint32_t count = rte_node_edge_count(tm->test_node[i].idx);
485 if (count != tm->test_node[i].node.nb_edges) {
486 printf("Test number of edges for node = %s failed Expected = %d, got = %d\n",
487 tm->test_node[i].node.name,
488 tm->test_node[i].node.nb_edges, count);
489 return -1;
490 }
491 }
492
493 /* Verify edge names */
494 for (i = 1; i < MAX_NODES; i++) {
495 uint32_t j, count;
496 char **next_edges;
497
498 count = rte_node_edge_get(tm->test_node[i].idx, NULL);
499 if (count != tm->test_node[i].node.nb_edges * sizeof(char *)) {
500 printf("Test number of edge count for node = %s failed Expected = %d, got = %d\n",
501 tm->test_node[i].node.name,
502 tm->test_node[i].node.nb_edges, count);
503 return -1;
504 }
505 next_edges = malloc(count);
506 count = rte_node_edge_get(tm->test_node[i].idx, next_edges);
507 if (count != tm->test_node[i].node.nb_edges) {
508 printf("Test number of edges for node = %s failed Expected = %d, got %d\n",
509 tm->test_node[i].node.name,
510 tm->test_node[i].node.nb_edges, count);
511 free(next_edges);
512 return -1;
513 }
514
515 for (j = 0; j < count; j++) {
516 if (strcmp(next_edges[j],
517 tm->test_node[i].node.next_nodes[j]) != 0) {
518 printf("Edge name miss match, expected = %s got = %s\n",
519 tm->test_node[i].node.next_nodes[j],
520 next_edges[j]);
521 free(next_edges);
522 return -1;
523 }
524 }
525 free(next_edges);
526 }
527
528 return 0;
529 }
530
531 static int
test_node_clone(void)532 test_node_clone(void)
533 {
534 test_main_t *tm = &test_main;
535 uint32_t node_id, dummy_id;
536 int i;
537
538 node_id = rte_node_from_name("test_node00");
539 tm->test_node[0].idx = node_id;
540
541 /* Clone with same name, should fail */
542 dummy_id = rte_node_clone(node_id, "test_node00");
543 if (!rte_node_is_invalid(dummy_id)) {
544 printf("Got valid id when clone with same name, Expecting fail\n");
545 return -1;
546 }
547
548 for (i = 1; i < MAX_NODES; i++) {
549 tm->test_node[i].idx =
550 rte_node_clone(node_id, tm->test_node[i].node.name);
551 if (rte_node_is_invalid(tm->test_node[i].idx)) {
552 printf("Got invalid node id\n");
553 return -1;
554 }
555 }
556
557 /* Clone from cloned node should fail */
558 dummy_id = rte_node_clone(tm->test_node[1].idx, "dummy_node");
559 if (!rte_node_is_invalid(dummy_id)) {
560 printf("Got valid node id when cloning from cloned node, expected fail\n");
561 return -1;
562 }
563
564 return 0;
565 }
566
567 static int
test_update_edges(void)568 test_update_edges(void)
569 {
570 test_main_t *tm = &test_main;
571 uint32_t node_id;
572 uint16_t count;
573 int i;
574
575 node_id = rte_node_from_name("test_node00");
576 count = rte_node_edge_update(node_id, 0,
577 tm->test_node[0].node.next_nodes,
578 tm->test_node[0].node.nb_edges);
579 if (count != tm->test_node[0].node.nb_edges) {
580 printf("Update edges failed expected: %d got = %d\n",
581 tm->test_node[0].node.nb_edges, count);
582 return -1;
583 }
584
585 for (i = 1; i < MAX_NODES; i++) {
586 count = rte_node_edge_update(tm->test_node[i].idx, 0,
587 tm->test_node[i].node.next_nodes,
588 tm->test_node[i].node.nb_edges);
589 if (count != tm->test_node[i].node.nb_edges) {
590 printf("Update edges failed expected: %d got = %d\n",
591 tm->test_node[i].node.nb_edges, count);
592 return -1;
593 }
594
595 count = rte_node_edge_shrink(tm->test_node[i].idx,
596 tm->test_node[i].node.nb_edges);
597 if (count != tm->test_node[i].node.nb_edges) {
598 printf("Shrink edges failed\n");
599 return -1;
600 }
601 }
602
603 return 0;
604 }
605
606 static int
test_create_graph(void)607 test_create_graph(void)
608 {
609 static const char *node_patterns_dummy[] = {
610 "test_node_source1", "test_node00",
611 "test_node00-test_node11", "test_node00-test_node22",
612 "test_node00-test_node33", "test_node00-dummy_node",
613 };
614 struct rte_graph_param gconf = {
615 .socket_id = SOCKET_ID_ANY,
616 .nb_node_patterns = 6,
617 .node_patterns = node_patterns_dummy,
618 };
619 uint32_t dummy_node_id;
620 uint32_t node_id;
621
622 node_id = rte_node_from_name("test_node00");
623 dummy_node_id = rte_node_clone(node_id, "dummy_node");
624 if (rte_node_is_invalid(dummy_node_id)) {
625 printf("Got invalid node id\n");
626 return -1;
627 }
628
629 graph_id = rte_graph_create("worker0", &gconf);
630 if (graph_id != RTE_GRAPH_ID_INVALID) {
631 printf("Graph creation success with isolated node, expected graph creation fail\n");
632 return -1;
633 }
634
635 gconf.nb_node_patterns = 5;
636 gconf.node_patterns = node_patterns;
637 graph_id = rte_graph_create("worker0", &gconf);
638 if (graph_id == RTE_GRAPH_ID_INVALID) {
639 printf("Graph creation failed with error = %d\n", rte_errno);
640 return -1;
641 }
642 return 0;
643 }
644
645 static int
test_graph_walk(void)646 test_graph_walk(void)
647 {
648 struct rte_graph *graph = rte_graph_lookup("worker0");
649 int i;
650
651 if (!graph) {
652 printf("Graph lookup failed\n");
653 return -1;
654 }
655
656 for (i = 0; i < 5; i++)
657 rte_graph_walk(graph);
658 return 0;
659 }
660
661 static int
test_graph_lookup_functions(void)662 test_graph_lookup_functions(void)
663 {
664 test_main_t *tm = &test_main;
665 struct rte_node *node;
666 int i;
667
668 for (i = 0; i < MAX_NODES; i++) {
669 node = rte_graph_node_get(graph_id, tm->test_node[i].idx);
670 if (!node) {
671 printf("rte_graph_node_get, failed for node = %d\n",
672 tm->test_node[i].idx);
673 return -1;
674 }
675
676 if (tm->test_node[i].idx != node->id) {
677 printf("Node id didn't match, expected = %d got = %d\n",
678 tm->test_node[i].idx, node->id);
679 return 0;
680 }
681
682 if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
683 printf("Node name didn't match, expected = %s got %s\n",
684 node_names[i], node->name);
685 return -1;
686 }
687 }
688
689 for (i = 0; i < MAX_NODES; i++) {
690 node = rte_graph_node_get_by_name("worker0", node_names[i]);
691 if (!node) {
692 printf("rte_graph_node_get, failed for node = %d\n",
693 tm->test_node[i].idx);
694 return -1;
695 }
696
697 if (tm->test_node[i].idx != node->id) {
698 printf("Node id didn't match, expected = %d got = %d\n",
699 tm->test_node[i].idx, node->id);
700 return 0;
701 }
702
703 if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
704 printf("Node name didn't match, expected = %s got %s\n",
705 node_names[i], node->name);
706 return -1;
707 }
708 }
709
710 return 0;
711 }
712
713 static int
graph_cluster_stats_cb_t(bool is_first,bool is_last,void * cookie,const struct rte_graph_cluster_node_stats * st)714 graph_cluster_stats_cb_t(bool is_first, bool is_last, void *cookie,
715 const struct rte_graph_cluster_node_stats *st)
716 {
717 int i;
718
719 RTE_SET_USED(is_first);
720 RTE_SET_USED(is_last);
721 RTE_SET_USED(cookie);
722
723 for (i = 0; i < MAX_NODES + 1; i++) {
724 rte_node_t id = rte_node_from_name(node_patterns[i]);
725 if (id == st->id) {
726 if (obj_stats[i] != st->objs) {
727 printf("Obj count miss match for node = %s expected = %"PRId64", got=%"PRId64"\n",
728 node_patterns[i], obj_stats[i],
729 st->objs);
730 return -1;
731 }
732
733 if (fn_calls[i] != st->calls) {
734 printf("Func call miss match for node = %s expected = %"PRId64", got = %"PRId64"\n",
735 node_patterns[i], fn_calls[i],
736 st->calls);
737 return -1;
738 }
739 }
740 }
741 return 0;
742 }
743
744 static int
test_print_stats(void)745 test_print_stats(void)
746 {
747 struct rte_graph_cluster_stats_param s_param;
748 struct rte_graph_cluster_stats *stats;
749 const char *pattern = "worker0";
750
751 if (!rte_graph_has_stats_feature())
752 return 0;
753
754 /* Prepare stats object */
755 memset(&s_param, 0, sizeof(s_param));
756 s_param.f = stdout;
757 s_param.socket_id = SOCKET_ID_ANY;
758 s_param.graph_patterns = &pattern;
759 s_param.nb_graph_patterns = 1;
760 s_param.fn = graph_cluster_stats_cb_t;
761
762 stats = rte_graph_cluster_stats_create(&s_param);
763 if (stats == NULL) {
764 printf("Unable to get stats\n");
765 return -1;
766 }
767 /* Clear screen and move to top left */
768 rte_graph_cluster_stats_get(stats, 0);
769 rte_graph_cluster_stats_destroy(stats);
770
771 return 0;
772 }
773
774 static int
graph_setup(void)775 graph_setup(void)
776 {
777 int i, j;
778
779 static const struct rte_mbuf_dynfield graph_dynfield_desc = {
780 .name = "test_graph_dynfield",
781 .size = sizeof(graph_dynfield_t),
782 .align = __alignof__(graph_dynfield_t),
783 };
784 graph_dynfield_offset =
785 rte_mbuf_dynfield_register(&graph_dynfield_desc);
786 if (graph_dynfield_offset < 0) {
787 printf("Cannot register mbuf field\n");
788 return TEST_FAILED;
789 }
790
791 for (i = 0; i <= MAX_NODES; i++) {
792 for (j = 0; j < MBUFF_SIZE; j++)
793 mbuf_p[i][j] = &mbuf[i][j];
794 }
795 if (test_node_clone()) {
796 printf("test_node_clone: fail\n");
797 return -1;
798 }
799 printf("test_node_clone: pass\n");
800
801 return 0;
802 }
803
804 static void
graph_teardown(void)805 graph_teardown(void)
806 {
807 int id;
808
809 id = rte_graph_destroy(rte_graph_from_name("worker0"));
810 if (id)
811 printf("Graph Destroy failed\n");
812 }
813
814 static struct unit_test_suite graph_testsuite = {
815 .suite_name = "Graph library test suite",
816 .setup = graph_setup,
817 .teardown = graph_teardown,
818 .unit_test_cases = {
819 TEST_CASE(test_update_edges),
820 TEST_CASE(test_lookup_functions),
821 TEST_CASE(test_create_graph),
822 TEST_CASE(test_graph_lookup_functions),
823 TEST_CASE(test_graph_walk),
824 TEST_CASE(test_print_stats),
825 TEST_CASES_END(), /**< NULL terminate unit test array */
826 },
827 };
828
829 static int
graph_autotest_fn(void)830 graph_autotest_fn(void)
831 {
832 return unit_test_suite_runner(&graph_testsuite);
833 }
834
835 REGISTER_TEST_COMMAND(graph_autotest, graph_autotest_fn);
836
837 static int
test_node_list_dump(void)838 test_node_list_dump(void)
839 {
840 rte_node_list_dump(stdout);
841
842 return TEST_SUCCESS;
843 }
844 REGISTER_TEST_COMMAND(node_list_dump, test_node_list_dump);
845