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