Branch data Line data Source code
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
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 *
59 : : graph_field(struct rte_mbuf *mbuf)
60 : : {
61 : 21868 : 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
143 : 25 : node_init(const struct rte_graph *graph, struct rte_node *node)
144 : : {
145 : : RTE_SET_USED(graph);
146 : 25 : *(uint32_t *)node->ctx = node->id;
147 : :
148 : 25 : 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 : 235 : 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 : 235 : RTE_NODE_REGISTER(test_node0);
167 : :
168 : : uint16_t
169 : 5 : test_node_worker_source(struct rte_graph *graph, struct rte_node *node,
170 : : void **objs, uint16_t nb_objs)
171 : : {
172 : 5 : 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 : 5 : obj_node0 = nb_objs * obj_node0 * 0.01;
184 : : next = 0;
185 : 5 : next_stream = rte_node_next_stream_get(graph, node, next, obj_node0);
186 [ + + ]: 413 : for (i = 0; i < obj_node0; i++) {
187 : 408 : data = &mbuf[0][i];
188 : 408 : *graph_field(data) = ((uint64_t)tm->test_node[0].idx << 32) | i;
189 [ + + ]: 408 : if ((i + 1) == obj_node0)
190 : 4 : *graph_field(data) |= (1 << 16);
191 : 408 : 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 : 5 : obj_node1 = nb_objs - obj_node0;
197 : : next = 1;
198 : 5 : next_stream = rte_node_next_stream_get(graph, node, next, obj_node1);
199 [ + + ]: 877 : for (i = 0; i < obj_node1; i++) {
200 : 872 : data = &mbuf[0][obj_node0 + i];
201 : 872 : *graph_field(data) = ((uint64_t)tm->test_node[1].idx << 32) | i;
202 [ + + ]: 872 : if ((i + 1) == obj_node1)
203 : 5 : *graph_field(data) |= (1 << 16);
204 : 872 : next_stream[i] = &mbuf[0][obj_node0 + i];
205 : : }
206 : :
207 : : rte_node_next_stream_put(graph, node, next, obj_node1);
208 : 5 : obj_stats[0] += nb_objs;
209 : 5 : fn_calls[0] += 1;
210 : 5 : return nb_objs;
211 : : }
212 : :
213 : : uint16_t
214 : 34 : 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 [ + + ]: 34 : if (*(uint32_t *)node->ctx == test_node0.id) {
220 : 9 : 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 : 9 : obj_stats[1] += nb_objs;
227 : 9 : fn_calls[1] += 1;
228 : :
229 [ + + ]: 2977 : for (i = 0; i < nb_objs; i++) {
230 : 2968 : data = (struct rte_mbuf *)objs[i];
231 [ - + ]: 2968 : if ((*graph_field(data) >> 32) != tm->test_node[0].idx) {
232 : 0 : 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 : 0 : goto end;
237 : : }
238 : :
239 [ - + ]: 2968 : if ((*graph_field(data) & 0xffff) != (i - count)) {
240 : : printf("Expected buff count miss match at "
241 : : "node 0\n");
242 : 0 : goto end;
243 : : }
244 : :
245 [ + + ]: 2968 : if (*graph_field(data) & (0x1 << 16))
246 : 9 : count = i + 1;
247 [ + + ]: 2968 : if (*graph_field(data) & (0x1 << 17))
248 : : second_pass = 1;
249 : : }
250 : :
251 [ - + ]: 9 : if (count != i) {
252 : : printf("Count mismatch at node 0\n");
253 : 0 : goto end;
254 : : }
255 : :
256 : 9 : obj_node0 = nb_objs * obj_node0 * 0.01;
257 [ + + ]: 1983 : for (i = 0; i < obj_node0; i++) {
258 : 1974 : data = &mbuf[1][i];
259 : 1974 : *graph_field(data) =
260 : 1974 : ((uint64_t)tm->test_node[1].idx << 32) | i;
261 [ + + ]: 1974 : if ((i + 1) == obj_node0)
262 : 9 : *graph_field(data) |= (1 << 16);
263 [ + + ]: 1974 : if (second_pass)
264 : 1738 : *graph_field(data) |= (1 << 17);
265 : : }
266 : 9 : rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[1][0],
267 : : obj_node0);
268 : :
269 : 9 : obj_node1 = nb_objs - obj_node0;
270 [ + + ]: 1003 : for (i = 0; i < obj_node1; i++) {
271 : 994 : data = &mbuf[1][obj_node0 + i];
272 : 994 : *graph_field(data) =
273 : 994 : ((uint64_t)tm->test_node[2].idx << 32) | i;
274 [ + + ]: 994 : if ((i + 1) == obj_node1)
275 : 9 : *graph_field(data) |= (1 << 16);
276 [ + + ]: 994 : if (second_pass)
277 : 822 : *graph_field(data) |= (1 << 17);
278 : : }
279 : 9 : rte_node_enqueue(graph, node, 1, (void **)&mbuf_p[1][obj_node0],
280 : : obj_node1);
281 : :
282 [ + + ]: 25 : } else if (*(uint32_t *)node->ctx == tm->test_node[1].idx) {
283 : 10 : test_node1_worker(graph, node, objs, nb_objs);
284 [ + + ]: 15 : } else if (*(uint32_t *)node->ctx == tm->test_node[2].idx) {
285 : 10 : test_node2_worker(graph, node, objs, nb_objs);
286 [ + - ]: 5 : } else if (*(uint32_t *)node->ctx == tm->test_node[3].idx) {
287 : 5 : test_node3_worker(graph, node, objs, nb_objs);
288 : : } else {
289 : : printf("Unexpected node context\n");
290 : : }
291 : :
292 : 34 : end:
293 : 34 : return nb_objs;
294 : : }
295 : :
296 : : uint16_t
297 : 10 : 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 : 10 : obj_stats[2] += nb_objs;
308 : 10 : fn_calls[2] += 1;
309 [ + + ]: 2856 : for (i = 0; i < nb_objs; i++) {
310 : 2846 : data = (struct rte_mbuf *)objs[i];
311 [ - + ]: 2846 : if ((*graph_field(data) >> 32) != tm->test_node[1].idx) {
312 : 0 : 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 : 0 : goto end;
317 : : }
318 : :
319 [ - + ]: 2846 : if ((*graph_field(data) & 0xffff) != (i - count)) {
320 : : printf("Expected buff count miss match at node 1\n");
321 : 0 : goto end;
322 : : }
323 : :
324 [ + + ]: 2846 : if (*graph_field(data) & (0x1 << 16))
325 : 14 : count = i + 1;
326 [ + + ]: 2846 : if (*graph_field(data) & (0x1 << 17))
327 : : second_pass = 1;
328 : : }
329 : :
330 [ + - ]: 10 : if (count != i) {
331 : : printf("Count mismatch at node 1\n");
332 : 0 : goto end;
333 : : }
334 : :
335 : : obj_node0 = nb_objs;
336 [ + + ]: 2856 : for (i = 0; i < obj_node0; i++) {
337 : 2846 : data = &mbuf[2][i];
338 : 2846 : *graph_field(data) = ((uint64_t)tm->test_node[2].idx << 32) | i;
339 [ + + ]: 2846 : if ((i + 1) == obj_node0)
340 : 10 : *graph_field(data) |= (1 << 16);
341 [ + + ]: 2846 : if (second_pass)
342 : 1738 : *graph_field(data) |= (1 << 17);
343 : : }
344 : 10 : rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[2][0], obj_node0);
345 : :
346 : 10 : end:
347 : 10 : return nb_objs;
348 : : }
349 : :
350 : : uint16_t
351 : 10 : 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 : 10 : obj_stats[3] += nb_objs;
362 : 10 : fn_calls[3] += 1;
363 [ + + ]: 3850 : for (i = 0; i < nb_objs; i++) {
364 : 3840 : data = (struct rte_mbuf *)objs[i];
365 [ - + ]: 3840 : if ((*graph_field(data) >> 32) != tm->test_node[2].idx) {
366 : 0 : 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 : 0 : goto end;
371 : : }
372 : :
373 [ - + ]: 3840 : if ((*graph_field(data) & 0xffff) != (i - count)) {
374 : : printf("Expected buff count miss match at node 2\n");
375 : 0 : goto end;
376 : : }
377 : :
378 [ + + ]: 3840 : if (*graph_field(data) & (0x1 << 16))
379 : 19 : count = i + 1;
380 [ + + ]: 3840 : if (*graph_field(data) & (0x1 << 17))
381 : : second_pass = 1;
382 : : }
383 : :
384 [ - + ]: 10 : if (count != i) {
385 : : printf("Count mismatch at node 2\n");
386 : 0 : goto end;
387 : : }
388 : :
389 [ + + ]: 10 : if (!second_pass) {
390 : : obj_node0 = nb_objs;
391 [ + + ]: 1285 : for (i = 0; i < obj_node0; i++) {
392 : 1280 : data = &mbuf[3][i];
393 : 1280 : *graph_field(data) =
394 : 1280 : ((uint64_t)tm->test_node[3].idx << 32) | i;
395 [ + + ]: 1280 : if ((i + 1) == obj_node0)
396 : 5 : *graph_field(data) |= (1 << 16);
397 : : }
398 : 5 : rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[3][0],
399 : : obj_node0);
400 : : }
401 : :
402 : 5 : end:
403 : 10 : return nb_objs;
404 : : }
405 : :
406 : : uint16_t
407 : 5 : 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 : 5 : obj_stats[4] += nb_objs;
418 : 5 : fn_calls[4] += 1;
419 [ + + ]: 1285 : for (i = 0; i < nb_objs; i++) {
420 : 1280 : data = (struct rte_mbuf *)objs[i];
421 [ - + ]: 1280 : if ((*graph_field(data) >> 32) != tm->test_node[3].idx) {
422 : 0 : 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 : 0 : goto end;
427 : : }
428 : :
429 [ - + ]: 1280 : if ((*graph_field(data) & 0xffff) != (i - count)) {
430 : : printf("Expected buff count miss match at node 3\n");
431 : 0 : goto end;
432 : : }
433 : :
434 [ + + ]: 1280 : if (*graph_field(data) & (0x1 << 16))
435 : 5 : count = i + 1;
436 [ - + ]: 1280 : if (*graph_field(data) & (0x1 << 17))
437 : : second_pass = 1;
438 : : }
439 : :
440 [ - + ]: 5 : if (count != i) {
441 : : printf("Count mismatch at node 3\n");
442 : 0 : goto end;
443 : : }
444 : :
445 [ - + ]: 5 : if (second_pass) {
446 : : printf("Unexpected buffers are at node 3\n");
447 : 0 : goto end;
448 : : } else {
449 : 5 : obj_node0 = nb_objs * 2;
450 [ + + ]: 2565 : for (i = 0; i < obj_node0; i++) {
451 : 2560 : data = &mbuf[4][i];
452 : : *graph_field(data) =
453 : 2560 : ((uint64_t)tm->test_node[0].idx << 32) | i;
454 : 2560 : *graph_field(data) |= (1 << 17);
455 [ + + ]: 2560 : if ((i + 1) == obj_node0)
456 : 5 : *graph_field(data) |= (1 << 16);
457 : : }
458 : 5 : rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[4][0],
459 : : obj_node0);
460 : : }
461 : :
462 : 5 : end:
463 : 5 : return nb_objs;
464 : : }
465 : :
466 : : static int
467 : 1 : test_lookup_functions(void)
468 : : {
469 : : test_main_t *tm = &test_main;
470 : : int i;
471 : :
472 : : /* Verify the name with ID */
473 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
474 : 3 : char *name = rte_node_id_to_name(tm->test_node[i].idx);
475 [ - + ]: 3 : 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 : 0 : return -1;
480 : : }
481 : : }
482 : :
483 : : /* Verify by name */
484 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
485 : 3 : uint32_t idx = rte_node_from_name(node_names[i]);
486 [ - + ]: 3 : if (idx != tm->test_node[i].idx) {
487 : 0 : 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 : 0 : return -1;
491 : : }
492 : : }
493 : :
494 : : /* Verify edge count */
495 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
496 : 3 : uint32_t count = rte_node_edge_count(tm->test_node[i].idx);
497 [ - + ]: 3 : if (count != tm->test_node[i].node.nb_edges) {
498 : 0 : printf("Test number of edges for node = %s failed Expected = %d, got = %d\n",
499 : 0 : tm->test_node[i].node.name,
500 : : tm->test_node[i].node.nb_edges, count);
501 : 0 : return -1;
502 : : }
503 : : }
504 : :
505 : : /* Verify edge names */
506 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
507 : : uint32_t j, count;
508 : : char **next_edges;
509 : :
510 : 3 : count = rte_node_edge_get(tm->test_node[i].idx, NULL);
511 [ - + ]: 3 : if (count != tm->test_node[i].node.nb_edges * sizeof(char *)) {
512 : 0 : printf("Test number of edge count for node = %s failed Expected = %d, got = %d\n",
513 : 0 : tm->test_node[i].node.name,
514 : : tm->test_node[i].node.nb_edges, count);
515 : 0 : return -1;
516 : : }
517 : 3 : next_edges = malloc(count);
518 : 3 : count = rte_node_edge_get(tm->test_node[i].idx, next_edges);
519 [ - + ]: 3 : if (count != tm->test_node[i].node.nb_edges) {
520 : 0 : printf("Test number of edges for node = %s failed Expected = %d, got %d\n",
521 : 0 : tm->test_node[i].node.name,
522 : : tm->test_node[i].node.nb_edges, count);
523 : 0 : free(next_edges);
524 : 0 : return -1;
525 : : }
526 : :
527 [ + + ]: 6 : for (j = 0; j < count; j++) {
528 [ - + ]: 3 : 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 : 0 : free(next_edges);
534 : 0 : return -1;
535 : : }
536 : : }
537 : 3 : free(next_edges);
538 : : }
539 : :
540 : : return 0;
541 : : }
542 : :
543 : : static int
544 : 1 : test_node_clone(void)
545 : : {
546 : : test_main_t *tm = &test_main;
547 : : uint32_t node_id, dummy_id;
548 : : int i;
549 : :
550 : 1 : node_id = rte_node_from_name("test_node00");
551 : 1 : tm->test_node[0].idx = node_id;
552 : :
553 : 1 : dummy_id = rte_node_clone(node_id, "test_node00");
554 [ - + ]: 1 : if (rte_node_is_invalid(dummy_id)) {
555 : : printf("Got invalid id when clone, Expecting fail\n");
556 : 0 : return -1;
557 : : }
558 : :
559 : : /* Clone with same name, should fail */
560 : 1 : dummy_id = rte_node_clone(node_id, "test_node00");
561 [ - + ]: 1 : if (!rte_node_is_invalid(dummy_id)) {
562 : : printf("Got valid id when clone with same name, Expecting fail\n");
563 : 0 : return -1;
564 : : }
565 : :
566 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
567 : 3 : tm->test_node[i].idx =
568 : 3 : rte_node_clone(node_id, tm->test_node[i].node.name);
569 [ - + ]: 3 : if (rte_node_is_invalid(tm->test_node[i].idx)) {
570 : : printf("Got invalid node id\n");
571 : 0 : return -1;
572 : : }
573 : : }
574 : :
575 : : /* Clone from cloned node should fail */
576 : 1 : dummy_id = rte_node_clone(tm->test_node[1].idx, "dummy_node");
577 [ - + ]: 1 : if (!rte_node_is_invalid(dummy_id)) {
578 : : printf("Got valid node id when cloning from cloned node, expected fail\n");
579 : 0 : return -1;
580 : : }
581 : :
582 : : return 0;
583 : : }
584 : :
585 : : static int
586 : 1 : 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 : 1 : node_id = rte_node_from_name("test_node00");
594 : 1 : count = rte_node_edge_update(node_id, 0,
595 : : tm->test_node[0].node.next_nodes,
596 : 1 : tm->test_node[0].node.nb_edges);
597 [ - + ]: 1 : if (count != tm->test_node[0].node.nb_edges) {
598 : 0 : printf("Update edges failed expected: %d got = %d\n",
599 : : tm->test_node[0].node.nb_edges, count);
600 : 0 : return -1;
601 : : }
602 : :
603 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
604 : 3 : count = rte_node_edge_update(tm->test_node[i].idx, 0,
605 : 3 : tm->test_node[i].node.next_nodes,
606 : 3 : tm->test_node[i].node.nb_edges);
607 [ - + ]: 3 : if (count != tm->test_node[i].node.nb_edges) {
608 : 0 : printf("Update edges failed expected: %d got = %d\n",
609 : : tm->test_node[i].node.nb_edges, count);
610 : 0 : return -1;
611 : : }
612 : :
613 : 3 : count = rte_node_edge_shrink(tm->test_node[i].idx,
614 : : tm->test_node[i].node.nb_edges);
615 [ - + ]: 3 : if (count != tm->test_node[i].node.nb_edges) {
616 : : printf("Shrink edges failed\n");
617 : 0 : return -1;
618 : : }
619 : : }
620 : :
621 : : return 0;
622 : : }
623 : :
624 : : static int
625 : 1 : 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 : 1 : 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 : 1 : node_id = rte_node_from_name("test_node00");
641 : 1 : dummy_node_id = rte_node_clone(node_id, "dummy_node");
642 [ - + ]: 1 : if (rte_node_is_invalid(dummy_node_id)) {
643 : : printf("Got invalid node id\n");
644 : 0 : return -1;
645 : : }
646 : :
647 : 1 : graph_id = rte_graph_create("worker0", &gconf);
648 [ - + ]: 1 : if (graph_id != RTE_GRAPH_ID_INVALID) {
649 : : printf("Graph creation success with isolated node, expected graph creation fail\n");
650 : 0 : return -1;
651 : : }
652 : :
653 : 1 : gconf.nb_node_patterns = 5;
654 : 1 : gconf.node_patterns = node_patterns;
655 : 1 : graph_id = rte_graph_create("worker0", &gconf);
656 [ - + ]: 1 : if (graph_id == RTE_GRAPH_ID_INVALID) {
657 : 0 : printf("Graph creation failed with error = %d\n", rte_errno);
658 : 0 : return -1;
659 : : }
660 : : return 0;
661 : : }
662 : :
663 : : static int
664 : 1 : test_graph_clone(void)
665 : : {
666 : : rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID;
667 : : rte_graph_t main_graph_id = RTE_GRAPH_ID_INVALID;
668 : 1 : struct rte_graph_param graph_conf = {0};
669 : : int ret = 0;
670 : :
671 : 1 : main_graph_id = rte_graph_from_name("worker0");
672 [ - + ]: 1 : if (main_graph_id == RTE_GRAPH_ID_INVALID) {
673 : : printf("Must create main graph first\n");
674 : : ret = -1;
675 : : }
676 : :
677 : 1 : graph_conf.dispatch.mp_capacity = 1024;
678 : 1 : graph_conf.dispatch.wq_size_max = 32;
679 : :
680 : 1 : cloned_graph_id = rte_graph_clone(main_graph_id, "cloned-test0", &graph_conf);
681 : :
682 [ - + ]: 1 : if (cloned_graph_id == RTE_GRAPH_ID_INVALID) {
683 : 0 : printf("Graph creation failed with error = %d\n", rte_errno);
684 : : ret = -1;
685 : : }
686 : :
687 [ - + ]: 1 : if (strcmp(rte_graph_id_to_name(cloned_graph_id), "worker0-cloned-test0")) {
688 : 0 : printf("Cloned graph should name as %s but get %s\n", "worker0-cloned-test",
689 : : rte_graph_id_to_name(cloned_graph_id));
690 : : ret = -1;
691 : : }
692 : :
693 : 1 : rte_graph_destroy(cloned_graph_id);
694 : :
695 : 1 : return ret;
696 : : }
697 : :
698 : : static int
699 : 1 : test_graph_model_mcore_dispatch_node_lcore_affinity_set(void)
700 : : {
701 : : rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID;
702 : : unsigned int worker_lcore = RTE_MAX_LCORE;
703 : 1 : struct rte_graph_param graph_conf = {0};
704 : : rte_node_t nid = RTE_NODE_ID_INVALID;
705 : 1 : char node_name[64] = "test_node00";
706 : : struct rte_node *node;
707 : : int ret = 0;
708 : :
709 : 1 : worker_lcore = rte_get_next_lcore(worker_lcore, true, 1);
710 : 1 : ret = rte_graph_model_mcore_dispatch_node_lcore_affinity_set(node_name, worker_lcore);
711 [ + - ]: 1 : if (ret == 0)
712 : : printf("Set node %s affinity to lcore %u\n", node_name, worker_lcore);
713 : :
714 : 1 : nid = rte_node_from_name(node_name);
715 : 1 : cloned_graph_id = rte_graph_clone(graph_id, "cloned-test1", &graph_conf);
716 : 1 : node = rte_graph_node_get(cloned_graph_id, nid);
717 : :
718 [ - + ]: 1 : if (node->dispatch.lcore_id != worker_lcore) {
719 : : printf("set node affinity failed\n");
720 : : ret = -1;
721 : : }
722 : :
723 : 1 : rte_graph_destroy(cloned_graph_id);
724 : :
725 : 1 : return ret;
726 : : }
727 : :
728 : : static int
729 : 1 : test_graph_model_mcore_dispatch_core_bind_unbind(void)
730 : : {
731 : : rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID;
732 : : unsigned int worker_lcore = RTE_MAX_LCORE;
733 : 1 : struct rte_graph_param graph_conf = {0};
734 : : struct rte_graph *graph;
735 : : int ret = 0;
736 : :
737 : 1 : worker_lcore = rte_get_next_lcore(worker_lcore, true, 1);
738 : 1 : cloned_graph_id = rte_graph_clone(graph_id, "cloned-test2", &graph_conf);
739 : :
740 : 1 : ret = rte_graph_worker_model_set(RTE_GRAPH_MODEL_MCORE_DISPATCH);
741 [ - + ]: 1 : if (ret != 0) {
742 : : printf("Set graph mcore dispatch model failed\n");
743 : 0 : goto fail;
744 : : }
745 : :
746 : 1 : ret = rte_graph_model_mcore_dispatch_core_bind(cloned_graph_id, worker_lcore);
747 [ - + ]: 1 : if (ret != 0) {
748 : 0 : printf("bind graph %d to lcore %u failed\n", graph_id, worker_lcore);
749 : 0 : goto fail;
750 : : }
751 : :
752 : 1 : graph = rte_graph_lookup("worker0-cloned-test2");
753 : :
754 [ - + ]: 1 : if (graph->dispatch.lcore_id != worker_lcore) {
755 : 0 : printf("bind graph %s(id:%d) with lcore %u failed\n",
756 : 0 : graph->name, graph->id, worker_lcore);
757 : : ret = -1;
758 : 0 : goto fail;
759 : : }
760 : :
761 : 1 : rte_graph_model_mcore_dispatch_core_unbind(cloned_graph_id);
762 [ + - ]: 1 : if (graph->dispatch.lcore_id != RTE_MAX_LCORE) {
763 : 0 : printf("unbind graph %s(id:%d) failed %d\n",
764 : 0 : graph->name, graph->id, graph->dispatch.lcore_id);
765 : : ret = -1;
766 : : }
767 : :
768 : 1 : fail:
769 : 1 : rte_graph_destroy(cloned_graph_id);
770 : :
771 : 1 : return ret;
772 : : }
773 : :
774 : : static int
775 : 1 : test_graph_worker_model_set_get(void)
776 : : {
777 : : rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID;
778 : 1 : struct rte_graph_param graph_conf = {0};
779 : : struct rte_graph *graph;
780 : : int ret = 0;
781 : :
782 : 1 : cloned_graph_id = rte_graph_clone(graph_id, "cloned-test3", &graph_conf);
783 : 1 : ret = rte_graph_worker_model_set(RTE_GRAPH_MODEL_MCORE_DISPATCH);
784 [ - + ]: 1 : if (ret != 0) {
785 : : printf("Set graph mcore dispatch model failed\n");
786 : 0 : goto fail;
787 : : }
788 : :
789 : 1 : graph = rte_graph_lookup("worker0-cloned-test3");
790 [ + - ]: 1 : if (rte_graph_worker_model_get(graph) != RTE_GRAPH_MODEL_MCORE_DISPATCH) {
791 : : printf("Get graph worker model failed\n");
792 : : ret = -1;
793 : : }
794 : :
795 : 1 : fail:
796 : 1 : rte_graph_destroy(cloned_graph_id);
797 : :
798 : 1 : return ret;
799 : : }
800 : :
801 : : static int
802 : 1 : test_graph_walk(void)
803 : : {
804 : 1 : struct rte_graph *graph = rte_graph_lookup("worker0");
805 : : int i;
806 : :
807 [ - + ]: 1 : if (!graph) {
808 : : printf("Graph lookup failed\n");
809 : 0 : return -1;
810 : : }
811 : :
812 [ + + ]: 6 : for (i = 0; i < 5; i++)
813 : 5 : rte_graph_walk(graph);
814 : : return 0;
815 : : }
816 : :
817 : : static int
818 : 1 : test_graph_lookup_functions(void)
819 : : {
820 : : test_main_t *tm = &test_main;
821 : : struct rte_node *node;
822 : : int i;
823 : :
824 [ + + ]: 5 : for (i = 0; i < MAX_NODES; i++) {
825 : 4 : node = rte_graph_node_get(graph_id, tm->test_node[i].idx);
826 [ - + ]: 4 : if (!node) {
827 : 0 : printf("rte_graph_node_get, failed for node = %d\n",
828 : : tm->test_node[i].idx);
829 : 0 : return -1;
830 : : }
831 : :
832 [ - + ]: 4 : if (tm->test_node[i].idx != node->id) {
833 : : printf("Node id didn't match, expected = %d got = %d\n",
834 : : tm->test_node[i].idx, node->id);
835 : 0 : return 0;
836 : : }
837 : :
838 [ - + ]: 4 : if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
839 : : printf("Node name didn't match, expected = %s got %s\n",
840 : : node_names[i], node->name);
841 : 0 : return -1;
842 : : }
843 : : }
844 : :
845 [ + + ]: 5 : for (i = 0; i < MAX_NODES; i++) {
846 : 4 : node = rte_graph_node_get_by_name("worker0", node_names[i]);
847 [ - + ]: 4 : if (!node) {
848 : 0 : printf("rte_graph_node_get, failed for node = %d\n",
849 : : tm->test_node[i].idx);
850 : 0 : return -1;
851 : : }
852 : :
853 [ - + ]: 4 : if (tm->test_node[i].idx != node->id) {
854 : : printf("Node id didn't match, expected = %d got = %d\n",
855 : : tm->test_node[i].idx, node->id);
856 : 0 : return 0;
857 : : }
858 : :
859 [ - + ]: 4 : if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
860 : : printf("Node name didn't match, expected = %s got %s\n",
861 : : node_names[i], node->name);
862 : 0 : return -1;
863 : : }
864 : : }
865 : :
866 : : return 0;
867 : : }
868 : :
869 : : static int
870 : 5 : graph_cluster_stats_cb_t(bool is_first, bool is_last, void *cookie,
871 : : const struct rte_graph_cluster_node_stats *st)
872 : : {
873 : : int i;
874 : :
875 : : RTE_SET_USED(is_first);
876 : : RTE_SET_USED(is_last);
877 : : RTE_SET_USED(cookie);
878 : :
879 [ + + ]: 30 : for (i = 0; i < MAX_NODES + 1; i++) {
880 : 25 : rte_node_t id = rte_node_from_name(node_patterns[i]);
881 [ + + ]: 25 : if (id == st->id) {
882 [ - + ]: 5 : if (obj_stats[i] != st->objs) {
883 : 0 : printf("Obj count miss match for node = %s expected = %"PRId64", got=%"PRId64"\n",
884 : : node_patterns[i], obj_stats[i],
885 : : st->objs);
886 : 0 : return -1;
887 : : }
888 : :
889 [ - + ]: 5 : if (fn_calls[i] != st->calls) {
890 : 0 : printf("Func call miss match for node = %s expected = %"PRId64", got = %"PRId64"\n",
891 : : node_patterns[i], fn_calls[i],
892 : : st->calls);
893 : 0 : return -1;
894 : : }
895 : : }
896 : : }
897 : : return 0;
898 : : }
899 : :
900 : : static int
901 : 1 : test_print_stats(void)
902 : : {
903 : : struct rte_graph_cluster_stats_param s_param;
904 : : struct rte_graph_cluster_stats *stats;
905 : 1 : const char *pattern = "worker0";
906 : :
907 : : if (!rte_graph_has_stats_feature())
908 : : return 0;
909 : :
910 : : /* Prepare stats object */
911 : : memset(&s_param, 0, sizeof(s_param));
912 : 1 : s_param.f = stdout;
913 : 1 : s_param.socket_id = SOCKET_ID_ANY;
914 : 1 : s_param.graph_patterns = &pattern;
915 : 1 : s_param.nb_graph_patterns = 1;
916 : 1 : s_param.fn = graph_cluster_stats_cb_t;
917 : :
918 : 1 : stats = rte_graph_cluster_stats_create(&s_param);
919 [ - + ]: 1 : if (stats == NULL) {
920 : : printf("Unable to get stats\n");
921 : 0 : return -1;
922 : : }
923 : : /* Clear screen and move to top left */
924 : 1 : rte_graph_cluster_stats_get(stats, 0);
925 : 1 : rte_graph_cluster_stats_destroy(stats);
926 : :
927 : 1 : return 0;
928 : : }
929 : :
930 : : static int
931 : 1 : graph_setup(void)
932 : : {
933 : : int i, j;
934 : :
935 : : static const struct rte_mbuf_dynfield graph_dynfield_desc = {
936 : : .name = "test_graph_dynfield",
937 : : .size = sizeof(graph_dynfield_t),
938 : : .align = __alignof__(graph_dynfield_t),
939 : : };
940 : 1 : graph_dynfield_offset =
941 : 1 : rte_mbuf_dynfield_register(&graph_dynfield_desc);
942 [ - + ]: 1 : if (graph_dynfield_offset < 0) {
943 : : printf("Cannot register mbuf field\n");
944 : 0 : return TEST_FAILED;
945 : : }
946 : :
947 [ + + ]: 6 : for (i = 0; i <= MAX_NODES; i++) {
948 [ + + ]: 2565 : for (j = 0; j < MBUFF_SIZE; j++)
949 : 2560 : mbuf_p[i][j] = &mbuf[i][j];
950 : : }
951 [ - + ]: 1 : if (test_node_clone()) {
952 : : printf("test_node_clone: fail\n");
953 : 0 : return -1;
954 : : }
955 : : printf("test_node_clone: pass\n");
956 : :
957 : 1 : return 0;
958 : : }
959 : :
960 : : static void
961 : 1 : graph_teardown(void)
962 : : {
963 : : int id;
964 : :
965 : 1 : id = rte_graph_destroy(rte_graph_from_name("worker0"));
966 [ - + ]: 1 : if (id)
967 : : printf("Graph Destroy failed\n");
968 : 1 : }
969 : :
970 : : static struct unit_test_suite graph_testsuite = {
971 : : .suite_name = "Graph library test suite",
972 : : .setup = graph_setup,
973 : : .teardown = graph_teardown,
974 : : .unit_test_cases = {
975 : : TEST_CASE(test_update_edges),
976 : : TEST_CASE(test_lookup_functions),
977 : : TEST_CASE(test_create_graph),
978 : : TEST_CASE(test_graph_clone),
979 : : TEST_CASE(test_graph_model_mcore_dispatch_node_lcore_affinity_set),
980 : : TEST_CASE(test_graph_model_mcore_dispatch_core_bind_unbind),
981 : : TEST_CASE(test_graph_worker_model_set_get),
982 : : TEST_CASE(test_graph_lookup_functions),
983 : : TEST_CASE(test_graph_walk),
984 : : TEST_CASE(test_print_stats),
985 : : TEST_CASES_END(), /**< NULL terminate unit test array */
986 : : },
987 : : };
988 : :
989 : : static int
990 : 1 : graph_autotest_fn(void)
991 : : {
992 : 1 : return unit_test_suite_runner(&graph_testsuite);
993 : : }
994 : :
995 : 235 : REGISTER_FAST_TEST(graph_autotest, true, true, graph_autotest_fn);
996 : :
997 : : static int
998 : 1 : test_node_list_dump(void)
999 : : {
1000 : 1 : rte_node_list_dump(stdout);
1001 : :
1002 : 1 : return TEST_SUCCESS;
1003 : : }
1004 : :
1005 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
1006 : :
1007 : 235 : REGISTER_FAST_TEST(node_list_dump, true, true, test_node_list_dump);
|