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 <stdalign.h>
11 : : #include <stdio.h>
12 : : #include <string.h>
13 : : #include <unistd.h>
14 : :
15 : : #include <rte_errno.h>
16 : :
17 : : #ifdef RTE_EXEC_ENV_WINDOWS
18 : : static int
19 : : test_node_list_dump(void)
20 : : {
21 : : printf("node_list_dump not supported on Windows, skipping test\n");
22 : : return TEST_SKIPPED;
23 : : }
24 : :
25 : : #else
26 : :
27 : : #include <rte_graph.h>
28 : : #include <rte_graph_worker.h>
29 : : #include <rte_mbuf.h>
30 : : #include <rte_mbuf_dyn.h>
31 : : #include <rte_random.h>
32 : :
33 : : static uint16_t test_node_worker_source(struct rte_graph *graph,
34 : : struct rte_node *node, void **objs,
35 : : uint16_t nb_objs);
36 : :
37 : : static uint16_t test_node0_worker(struct rte_graph *graph,
38 : : struct rte_node *node, void **objs,
39 : : uint16_t nb_objs);
40 : :
41 : : static uint16_t test_node1_worker(struct rte_graph *graph,
42 : : struct rte_node *node, void **objs,
43 : : uint16_t nb_objs);
44 : :
45 : : static uint16_t test_node2_worker(struct rte_graph *graph,
46 : : struct rte_node *node, void **objs,
47 : : uint16_t nb_objs);
48 : :
49 : : static uint16_t test_node3_worker(struct rte_graph *graph,
50 : : struct rte_node *node, void **objs,
51 : : uint16_t nb_objs);
52 : :
53 : : #define MBUFF_SIZE 512
54 : : #define MAX_NODES 4
55 : :
56 : : typedef uint64_t graph_dynfield_t;
57 : : static int graph_dynfield_offset = -1;
58 : :
59 : : static inline graph_dynfield_t *
60 : : graph_field(struct rte_mbuf *mbuf)
61 : : {
62 : 0 : return RTE_MBUF_DYNFIELD(mbuf, \
63 : : graph_dynfield_offset, graph_dynfield_t *);
64 : : }
65 : :
66 : : static struct rte_mbuf mbuf[MAX_NODES + 1][MBUFF_SIZE];
67 : : static void *mbuf_p[MAX_NODES + 1][MBUFF_SIZE];
68 : : static rte_graph_t graph_id;
69 : : static uint64_t obj_stats[MAX_NODES + 1];
70 : : static uint64_t fn_calls[MAX_NODES + 1];
71 : :
72 : : const char *node_patterns[] = {
73 : : "test_node_source1", "test_node00",
74 : : "test_node00-test_node11", "test_node00-test_node22",
75 : : "test_node00-test_node33",
76 : : };
77 : :
78 : : const char *node_names[] = {
79 : : "test_node00",
80 : : "test_node00-test_node11",
81 : : "test_node00-test_node22",
82 : : "test_node00-test_node33",
83 : : };
84 : :
85 : : struct test_node_register {
86 : : char name[RTE_NODE_NAMESIZE];
87 : : rte_node_process_t process;
88 : : uint16_t nb_edges;
89 : : const char *next_nodes[MAX_NODES];
90 : : };
91 : :
92 : : typedef struct {
93 : : uint32_t idx;
94 : : struct test_node_register node;
95 : : } test_node_t;
96 : :
97 : : typedef struct {
98 : : test_node_t test_node[MAX_NODES];
99 : : } test_main_t;
100 : :
101 : : static test_main_t test_main = {
102 : : .test_node = {
103 : : {
104 : : .node = {
105 : : .name = "test_node00",
106 : : .process = test_node0_worker,
107 : : .nb_edges = 2,
108 : : .next_nodes = {"test_node00-"
109 : : "test_node11",
110 : : "test_node00-"
111 : : "test_node22"},
112 : : },
113 : : },
114 : : {
115 : : .node = {
116 : : .name = "test_node11",
117 : : .process = test_node1_worker,
118 : : .nb_edges = 1,
119 : : .next_nodes = {"test_node00-"
120 : : "test_node22"},
121 : : },
122 : : },
123 : : {
124 : : .node = {
125 : : .name = "test_node22",
126 : : .process = test_node2_worker,
127 : : .nb_edges = 1,
128 : : .next_nodes = {"test_node00-"
129 : : "test_node33"},
130 : : },
131 : : },
132 : : {
133 : : .node = {
134 : : .name = "test_node33",
135 : : .process = test_node3_worker,
136 : : .nb_edges = 1,
137 : : .next_nodes = {"test_node00"},
138 : : },
139 : : },
140 : : },
141 : : };
142 : :
143 : : static int
144 : 50 : node_init(const struct rte_graph *graph, struct rte_node *node)
145 : : {
146 : : RTE_SET_USED(graph);
147 : 50 : *(uint32_t *)node->ctx = node->id;
148 : :
149 : 50 : return 0;
150 : : }
151 : :
152 : : static struct rte_node_register test_node_source = {
153 : : .name = "test_node_source1",
154 : : .process = test_node_worker_source,
155 : : .flags = RTE_NODE_SOURCE_F,
156 : : .nb_edges = 2,
157 : : .init = node_init,
158 : : .next_nodes = {"test_node00", "test_node00-test_node11"},
159 : : };
160 : 251 : RTE_NODE_REGISTER(test_node_source);
161 : :
162 : : static struct rte_node_register test_node0 = {
163 : : .name = "test_node00",
164 : : .process = test_node0_worker,
165 : : .init = node_init,
166 : : };
167 : 251 : RTE_NODE_REGISTER(test_node0);
168 : :
169 : : uint16_t
170 : 0 : test_node_worker_source(struct rte_graph *graph, struct rte_node *node,
171 : : void **objs, uint16_t nb_objs)
172 : : {
173 : 0 : uint32_t obj_node0 = rte_rand() % 100, obj_node1;
174 : : test_main_t *tm = &test_main;
175 : : struct rte_mbuf *data;
176 : : void **next_stream;
177 : : rte_node_t next;
178 : : uint32_t i;
179 : :
180 : : RTE_SET_USED(objs);
181 : : nb_objs = RTE_GRAPH_BURST_SIZE;
182 : :
183 : : /* Prepare stream for next node 0 */
184 : 0 : obj_node0 = nb_objs * obj_node0 * 0.01;
185 : : next = 0;
186 : 0 : next_stream = rte_node_next_stream_get(graph, node, next, obj_node0);
187 [ # # ]: 0 : for (i = 0; i < obj_node0; i++) {
188 : 0 : data = &mbuf[0][i];
189 : 0 : *graph_field(data) = ((uint64_t)tm->test_node[0].idx << 32) | i;
190 [ # # ]: 0 : if ((i + 1) == obj_node0)
191 : 0 : *graph_field(data) |= (1 << 16);
192 : 0 : next_stream[i] = &mbuf[0][i];
193 : : }
194 : : rte_node_next_stream_put(graph, node, next, obj_node0);
195 : :
196 : : /* Prepare stream for next node 1 */
197 : 0 : obj_node1 = nb_objs - obj_node0;
198 : : next = 1;
199 : 0 : next_stream = rte_node_next_stream_get(graph, node, next, obj_node1);
200 [ # # ]: 0 : for (i = 0; i < obj_node1; i++) {
201 : 0 : data = &mbuf[0][obj_node0 + i];
202 : 0 : *graph_field(data) = ((uint64_t)tm->test_node[1].idx << 32) | i;
203 [ # # ]: 0 : if ((i + 1) == obj_node1)
204 : 0 : *graph_field(data) |= (1 << 16);
205 : 0 : next_stream[i] = &mbuf[0][obj_node0 + i];
206 : : }
207 : :
208 : : rte_node_next_stream_put(graph, node, next, obj_node1);
209 : 0 : obj_stats[0] += nb_objs;
210 : 0 : fn_calls[0] += 1;
211 : 0 : return nb_objs;
212 : : }
213 : :
214 : : uint16_t
215 : 0 : test_node0_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
216 : : uint16_t nb_objs)
217 : : {
218 : : test_main_t *tm = &test_main;
219 : :
220 [ # # ]: 0 : if (*(uint32_t *)node->ctx == test_node0.id) {
221 : 0 : uint32_t obj_node0 = rte_rand() % 100, obj_node1;
222 : : struct rte_mbuf *data;
223 : : uint8_t second_pass = 0;
224 : : uint32_t count = 0;
225 : : uint32_t i;
226 : :
227 : 0 : obj_stats[1] += nb_objs;
228 : 0 : fn_calls[1] += 1;
229 : :
230 [ # # ]: 0 : for (i = 0; i < nb_objs; i++) {
231 : 0 : data = (struct rte_mbuf *)objs[i];
232 [ # # ]: 0 : if ((*graph_field(data) >> 32) != tm->test_node[0].idx) {
233 : 0 : printf("Data idx miss match at node 0, expected"
234 : : " = %u got = %u\n",
235 : : tm->test_node[0].idx,
236 : : (uint32_t)(*graph_field(data) >> 32));
237 : 0 : goto end;
238 : : }
239 : :
240 [ # # ]: 0 : if ((*graph_field(data) & 0xffff) != (i - count)) {
241 : : printf("Expected buff count miss match at "
242 : : "node 0\n");
243 : 0 : goto end;
244 : : }
245 : :
246 [ # # ]: 0 : if (*graph_field(data) & (0x1 << 16))
247 : 0 : count = i + 1;
248 [ # # ]: 0 : if (*graph_field(data) & (0x1 << 17))
249 : : second_pass = 1;
250 : : }
251 : :
252 [ # # ]: 0 : if (count != i) {
253 : : printf("Count mismatch at node 0\n");
254 : 0 : goto end;
255 : : }
256 : :
257 : 0 : obj_node0 = nb_objs * obj_node0 * 0.01;
258 [ # # ]: 0 : for (i = 0; i < obj_node0; i++) {
259 : 0 : data = &mbuf[1][i];
260 : 0 : *graph_field(data) =
261 : 0 : ((uint64_t)tm->test_node[1].idx << 32) | i;
262 [ # # ]: 0 : if ((i + 1) == obj_node0)
263 : 0 : *graph_field(data) |= (1 << 16);
264 [ # # ]: 0 : if (second_pass)
265 : 0 : *graph_field(data) |= (1 << 17);
266 : : }
267 : 0 : rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[1][0],
268 : : obj_node0);
269 : :
270 : 0 : obj_node1 = nb_objs - obj_node0;
271 [ # # ]: 0 : for (i = 0; i < obj_node1; i++) {
272 : 0 : data = &mbuf[1][obj_node0 + i];
273 : 0 : *graph_field(data) =
274 : 0 : ((uint64_t)tm->test_node[2].idx << 32) | i;
275 [ # # ]: 0 : if ((i + 1) == obj_node1)
276 : 0 : *graph_field(data) |= (1 << 16);
277 [ # # ]: 0 : if (second_pass)
278 : 0 : *graph_field(data) |= (1 << 17);
279 : : }
280 : 0 : rte_node_enqueue(graph, node, 1, (void **)&mbuf_p[1][obj_node0],
281 : : obj_node1);
282 : :
283 [ # # ]: 0 : } else if (*(uint32_t *)node->ctx == tm->test_node[1].idx) {
284 : 0 : test_node1_worker(graph, node, objs, nb_objs);
285 [ # # ]: 0 : } else if (*(uint32_t *)node->ctx == tm->test_node[2].idx) {
286 : 0 : test_node2_worker(graph, node, objs, nb_objs);
287 [ # # ]: 0 : } else if (*(uint32_t *)node->ctx == tm->test_node[3].idx) {
288 : 0 : test_node3_worker(graph, node, objs, nb_objs);
289 : : } else {
290 : : printf("Unexpected node context\n");
291 : : }
292 : :
293 : 0 : end:
294 : 0 : return nb_objs;
295 : : }
296 : :
297 : : uint16_t
298 : 0 : test_node1_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
299 : : uint16_t nb_objs)
300 : : {
301 : : test_main_t *tm = &test_main;
302 : : uint8_t second_pass = 0;
303 : : uint32_t obj_node0 = 0;
304 : : struct rte_mbuf *data;
305 : : uint32_t count = 0;
306 : : uint32_t i;
307 : :
308 : 0 : obj_stats[2] += nb_objs;
309 : 0 : fn_calls[2] += 1;
310 [ # # ]: 0 : for (i = 0; i < nb_objs; i++) {
311 : 0 : data = (struct rte_mbuf *)objs[i];
312 [ # # ]: 0 : if ((*graph_field(data) >> 32) != tm->test_node[1].idx) {
313 : 0 : printf("Data idx miss match at node 1, expected = %u"
314 : : " got = %u\n",
315 : : tm->test_node[1].idx,
316 : : (uint32_t)(*graph_field(data) >> 32));
317 : 0 : goto end;
318 : : }
319 : :
320 [ # # ]: 0 : if ((*graph_field(data) & 0xffff) != (i - count)) {
321 : : printf("Expected buff count miss match at node 1\n");
322 : 0 : goto end;
323 : : }
324 : :
325 [ # # ]: 0 : if (*graph_field(data) & (0x1 << 16))
326 : 0 : count = i + 1;
327 [ # # ]: 0 : if (*graph_field(data) & (0x1 << 17))
328 : : second_pass = 1;
329 : : }
330 : :
331 [ # # ]: 0 : if (count != i) {
332 : : printf("Count mismatch at node 1\n");
333 : 0 : goto end;
334 : : }
335 : :
336 : : obj_node0 = nb_objs;
337 [ # # ]: 0 : for (i = 0; i < obj_node0; i++) {
338 : 0 : data = &mbuf[2][i];
339 : 0 : *graph_field(data) = ((uint64_t)tm->test_node[2].idx << 32) | i;
340 [ # # ]: 0 : if ((i + 1) == obj_node0)
341 : 0 : *graph_field(data) |= (1 << 16);
342 [ # # ]: 0 : if (second_pass)
343 : 0 : *graph_field(data) |= (1 << 17);
344 : : }
345 : 0 : rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[2][0], obj_node0);
346 : :
347 : 0 : end:
348 : 0 : return nb_objs;
349 : : }
350 : :
351 : : uint16_t
352 : 0 : test_node2_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
353 : : uint16_t nb_objs)
354 : : {
355 : : test_main_t *tm = &test_main;
356 : : uint8_t second_pass = 0;
357 : : struct rte_mbuf *data;
358 : : uint32_t count = 0;
359 : : uint32_t obj_node0;
360 : : uint32_t i;
361 : :
362 : 0 : obj_stats[3] += nb_objs;
363 : 0 : fn_calls[3] += 1;
364 [ # # ]: 0 : for (i = 0; i < nb_objs; i++) {
365 : 0 : data = (struct rte_mbuf *)objs[i];
366 [ # # ]: 0 : if ((*graph_field(data) >> 32) != tm->test_node[2].idx) {
367 : 0 : printf("Data idx miss match at node 2, expected = %u"
368 : : " got = %u\n",
369 : : tm->test_node[2].idx,
370 : : (uint32_t)(*graph_field(data) >> 32));
371 : 0 : goto end;
372 : : }
373 : :
374 [ # # ]: 0 : if ((*graph_field(data) & 0xffff) != (i - count)) {
375 : : printf("Expected buff count miss match at node 2\n");
376 : 0 : goto end;
377 : : }
378 : :
379 [ # # ]: 0 : if (*graph_field(data) & (0x1 << 16))
380 : 0 : count = i + 1;
381 [ # # ]: 0 : if (*graph_field(data) & (0x1 << 17))
382 : : second_pass = 1;
383 : : }
384 : :
385 [ # # ]: 0 : if (count != i) {
386 : : printf("Count mismatch at node 2\n");
387 : 0 : goto end;
388 : : }
389 : :
390 [ # # ]: 0 : if (!second_pass) {
391 : : obj_node0 = nb_objs;
392 [ # # ]: 0 : for (i = 0; i < obj_node0; i++) {
393 : 0 : data = &mbuf[3][i];
394 : 0 : *graph_field(data) =
395 : 0 : ((uint64_t)tm->test_node[3].idx << 32) | i;
396 [ # # ]: 0 : if ((i + 1) == obj_node0)
397 : 0 : *graph_field(data) |= (1 << 16);
398 : : }
399 : 0 : rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[3][0],
400 : : obj_node0);
401 : : }
402 : :
403 : 0 : end:
404 : 0 : return nb_objs;
405 : : }
406 : :
407 : : uint16_t
408 : 0 : test_node3_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
409 : : uint16_t nb_objs)
410 : : {
411 : : test_main_t *tm = &test_main;
412 : : uint8_t second_pass = 0;
413 : : struct rte_mbuf *data;
414 : : uint32_t count = 0;
415 : : uint32_t obj_node0;
416 : : uint32_t i;
417 : :
418 : 0 : obj_stats[4] += nb_objs;
419 : 0 : fn_calls[4] += 1;
420 [ # # ]: 0 : for (i = 0; i < nb_objs; i++) {
421 : 0 : data = (struct rte_mbuf *)objs[i];
422 [ # # ]: 0 : if ((*graph_field(data) >> 32) != tm->test_node[3].idx) {
423 : 0 : printf("Data idx miss match at node 3, expected = %u"
424 : : " got = %u\n",
425 : : tm->test_node[3].idx,
426 : : (uint32_t)(*graph_field(data) >> 32));
427 : 0 : goto end;
428 : : }
429 : :
430 [ # # ]: 0 : if ((*graph_field(data) & 0xffff) != (i - count)) {
431 : : printf("Expected buff count miss match at node 3\n");
432 : 0 : goto end;
433 : : }
434 : :
435 [ # # ]: 0 : if (*graph_field(data) & (0x1 << 16))
436 : 0 : count = i + 1;
437 [ # # ]: 0 : if (*graph_field(data) & (0x1 << 17))
438 : : second_pass = 1;
439 : : }
440 : :
441 [ # # ]: 0 : if (count != i) {
442 : : printf("Count mismatch at node 3\n");
443 : 0 : goto end;
444 : : }
445 : :
446 [ # # ]: 0 : if (second_pass) {
447 : : printf("Unexpected buffers are at node 3\n");
448 : 0 : goto end;
449 : : } else {
450 : 0 : obj_node0 = nb_objs * 2;
451 [ # # ]: 0 : for (i = 0; i < obj_node0; i++) {
452 : 0 : data = &mbuf[4][i];
453 : : *graph_field(data) =
454 : 0 : ((uint64_t)tm->test_node[0].idx << 32) | i;
455 : 0 : *graph_field(data) |= (1 << 17);
456 [ # # ]: 0 : if ((i + 1) == obj_node0)
457 : 0 : *graph_field(data) |= (1 << 16);
458 : : }
459 : 0 : rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[4][0],
460 : : obj_node0);
461 : : }
462 : :
463 : 0 : end:
464 : 0 : return nb_objs;
465 : : }
466 : :
467 : : static int
468 : 1 : test_lookup_functions(void)
469 : : {
470 : : test_main_t *tm = &test_main;
471 : : int i;
472 : :
473 : : /* Verify the name with ID */
474 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
475 : 3 : char *name = rte_node_id_to_name(tm->test_node[i].idx);
476 [ - + ]: 3 : if (strcmp(name, node_names[i]) != 0) {
477 : : printf("Test node name verify by ID = %d failed "
478 : : "Expected = %s, got %s\n",
479 : : i, node_names[i], name);
480 : 0 : return -1;
481 : : }
482 : : }
483 : :
484 : : /* Verify by name */
485 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
486 : 3 : uint32_t idx = rte_node_from_name(node_names[i]);
487 [ - + ]: 3 : if (idx != tm->test_node[i].idx) {
488 : 0 : printf("Test node ID verify by name = %s failed "
489 : : "Expected = %d, got %d\n",
490 : : node_names[i], tm->test_node[i].idx, idx);
491 : 0 : return -1;
492 : : }
493 : : }
494 : :
495 : : /* Verify edge count */
496 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
497 : 3 : uint32_t count = rte_node_edge_count(tm->test_node[i].idx);
498 [ - + ]: 3 : if (count != tm->test_node[i].node.nb_edges) {
499 : 0 : printf("Test number of edges for node = %s failed Expected = %d, got = %d\n",
500 : 0 : tm->test_node[i].node.name,
501 : : tm->test_node[i].node.nb_edges, count);
502 : 0 : return -1;
503 : : }
504 : : }
505 : :
506 : : /* Verify edge names */
507 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
508 : : uint32_t j, count;
509 : : char **next_edges;
510 : :
511 : 3 : count = rte_node_edge_get(tm->test_node[i].idx, NULL);
512 [ - + ]: 3 : if (count != tm->test_node[i].node.nb_edges * sizeof(char *)) {
513 : 0 : printf("Test number of edge count for node = %s failed Expected = %d, got = %d\n",
514 : 0 : tm->test_node[i].node.name,
515 : : tm->test_node[i].node.nb_edges, count);
516 : 0 : return -1;
517 : : }
518 : 3 : next_edges = malloc(count);
519 : 3 : count = rte_node_edge_get(tm->test_node[i].idx, next_edges);
520 [ - + ]: 3 : if (count != tm->test_node[i].node.nb_edges) {
521 : 0 : printf("Test number of edges for node = %s failed Expected = %d, got %d\n",
522 : 0 : tm->test_node[i].node.name,
523 : : tm->test_node[i].node.nb_edges, count);
524 : 0 : free(next_edges);
525 : 0 : return -1;
526 : : }
527 : :
528 [ + + ]: 6 : for (j = 0; j < count; j++) {
529 [ - + ]: 3 : if (strcmp(next_edges[j],
530 : : tm->test_node[i].node.next_nodes[j]) != 0) {
531 : : printf("Edge name miss match, expected = %s got = %s\n",
532 : : tm->test_node[i].node.next_nodes[j],
533 : : next_edges[j]);
534 : 0 : free(next_edges);
535 : 0 : return -1;
536 : : }
537 : : }
538 : 3 : free(next_edges);
539 : : }
540 : :
541 : : return 0;
542 : : }
543 : :
544 : : static int
545 : 1 : test_node_clone(void)
546 : : {
547 : : test_main_t *tm = &test_main;
548 : : uint32_t node_id, dummy_id;
549 : : int i;
550 : :
551 : 1 : node_id = rte_node_from_name("test_node00");
552 : 1 : tm->test_node[0].idx = node_id;
553 : :
554 : 1 : dummy_id = rte_node_clone(node_id, "test_node00");
555 [ - + ]: 1 : if (rte_node_is_invalid(dummy_id)) {
556 : : printf("Got invalid id when clone, Expecting fail\n");
557 : 0 : return -1;
558 : : }
559 : :
560 : : /* Clone with same name, should fail */
561 : 1 : dummy_id = rte_node_clone(node_id, "test_node00");
562 [ - + ]: 1 : if (!rte_node_is_invalid(dummy_id)) {
563 : : printf("Got valid id when clone with same name, Expecting fail\n");
564 : 0 : return -1;
565 : : }
566 : :
567 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
568 : 3 : tm->test_node[i].idx =
569 : 3 : rte_node_clone(node_id, tm->test_node[i].node.name);
570 [ - + ]: 3 : if (rte_node_is_invalid(tm->test_node[i].idx)) {
571 : : printf("Got invalid node id\n");
572 : 0 : return -1;
573 : : }
574 : : }
575 : :
576 : : /* Clone from cloned node should fail */
577 : 1 : dummy_id = rte_node_clone(tm->test_node[1].idx, "dummy_node");
578 [ - + ]: 1 : if (!rte_node_is_invalid(dummy_id)) {
579 : : printf("Got valid node id when cloning from cloned node, expected fail\n");
580 : 0 : return -1;
581 : : }
582 : :
583 : : return 0;
584 : : }
585 : :
586 : : static int
587 : 1 : test_update_edges(void)
588 : : {
589 : : test_main_t *tm = &test_main;
590 : : uint32_t node_id;
591 : : uint16_t count;
592 : : int i;
593 : :
594 : 1 : node_id = rte_node_from_name("test_node00");
595 : 1 : count = rte_node_edge_update(node_id, 0,
596 : : tm->test_node[0].node.next_nodes,
597 : 1 : tm->test_node[0].node.nb_edges);
598 [ - + ]: 1 : if (count != tm->test_node[0].node.nb_edges) {
599 : 0 : printf("Update edges failed expected: %d got = %d\n",
600 : : tm->test_node[0].node.nb_edges, count);
601 : 0 : return -1;
602 : : }
603 : :
604 [ + + ]: 4 : for (i = 1; i < MAX_NODES; i++) {
605 : 3 : count = rte_node_edge_update(tm->test_node[i].idx, 0,
606 : 3 : tm->test_node[i].node.next_nodes,
607 : 3 : tm->test_node[i].node.nb_edges);
608 [ - + ]: 3 : if (count != tm->test_node[i].node.nb_edges) {
609 : 0 : printf("Update edges failed expected: %d got = %d\n",
610 : : tm->test_node[i].node.nb_edges, count);
611 : 0 : return -1;
612 : : }
613 : :
614 : 3 : count = rte_node_edge_shrink(tm->test_node[i].idx,
615 : : tm->test_node[i].node.nb_edges);
616 [ - + ]: 3 : if (count != tm->test_node[i].node.nb_edges) {
617 : : printf("Shrink edges failed\n");
618 : 0 : return -1;
619 : : }
620 : : }
621 : :
622 : : return 0;
623 : : }
624 : :
625 : : static int
626 : 1 : test_create_graph(void)
627 : : {
628 : : static const char *node_patterns_dummy[] = {
629 : : "test_node_source1", "test_node00",
630 : : "test_node00-test_node11", "test_node00-test_node22",
631 : : "test_node00-test_node33", "test_node00-dummy_node",
632 : : };
633 : 1 : struct rte_graph_param gconf = {
634 : : .socket_id = SOCKET_ID_ANY,
635 : : .nb_node_patterns = 6,
636 : : .node_patterns = node_patterns_dummy,
637 : : };
638 : : uint32_t dummy_node_id;
639 : : uint32_t node_id;
640 : :
641 : 1 : node_id = rte_node_from_name("test_node00");
642 : 1 : dummy_node_id = rte_node_clone(node_id, "dummy_node");
643 [ - + ]: 1 : if (rte_node_is_invalid(dummy_node_id)) {
644 : : printf("Got invalid node id\n");
645 : 0 : return -1;
646 : : }
647 : :
648 : 1 : graph_id = rte_graph_create("worker0", &gconf);
649 [ - + ]: 1 : if (graph_id != RTE_GRAPH_ID_INVALID) {
650 : : printf("Graph creation success with isolated node, expected graph creation fail\n");
651 : 0 : return -1;
652 : : }
653 : :
654 : 1 : gconf.nb_node_patterns = 5;
655 : 1 : gconf.node_patterns = node_patterns;
656 : 1 : graph_id = rte_graph_create("worker0", &gconf);
657 [ - + ]: 1 : if (graph_id == RTE_GRAPH_ID_INVALID) {
658 : 0 : printf("Graph creation failed with error = %d\n", rte_errno);
659 : 0 : return -1;
660 : : }
661 : : return 0;
662 : : }
663 : :
664 : : static int
665 : 1 : test_graph_clone(void)
666 : : {
667 : : rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID;
668 : : rte_graph_t main_graph_id = RTE_GRAPH_ID_INVALID;
669 : 1 : struct rte_graph_param graph_conf = {0};
670 : : int ret = 0;
671 : :
672 : 1 : main_graph_id = rte_graph_from_name("worker0");
673 [ - + ]: 1 : if (main_graph_id == RTE_GRAPH_ID_INVALID) {
674 : : printf("Must create main graph first\n");
675 : : ret = -1;
676 : : }
677 : :
678 : 1 : graph_conf.dispatch.mp_capacity = 1024;
679 : 1 : graph_conf.dispatch.wq_size_max = 32;
680 : :
681 : 1 : cloned_graph_id = rte_graph_clone(main_graph_id, "cloned-test0", &graph_conf);
682 : :
683 [ - + ]: 1 : if (cloned_graph_id == RTE_GRAPH_ID_INVALID) {
684 : 0 : printf("Graph creation failed with error = %d\n", rte_errno);
685 : : ret = -1;
686 : : }
687 : :
688 [ - + ]: 1 : if (strcmp(rte_graph_id_to_name(cloned_graph_id), "worker0-cloned-test0")) {
689 : 0 : printf("Cloned graph should name as %s but get %s\n", "worker0-cloned-test",
690 : : rte_graph_id_to_name(cloned_graph_id));
691 : : ret = -1;
692 : : }
693 : :
694 : 1 : rte_graph_destroy(cloned_graph_id);
695 : :
696 : 1 : return ret;
697 : : }
698 : :
699 : : static int
700 : 1 : test_graph_id_collisions(void)
701 : : {
702 : : static const char *node_patterns[] = {"test_node_source1", "test_node00"};
703 : 1 : struct rte_graph_param gconf = {
704 : : .socket_id = SOCKET_ID_ANY,
705 : : .nb_node_patterns = 2,
706 : : .node_patterns = node_patterns,
707 : : };
708 : : rte_graph_t g1, g2, g3, g4;
709 : :
710 : 1 : g1 = rte_graph_create("worker1", &gconf);
711 [ - + ]: 1 : if (g1 == RTE_GRAPH_ID_INVALID) {
712 : 0 : printf("Graph 1 creation failed with error = %d\n", rte_errno);
713 : 0 : return -1;
714 : : }
715 : 1 : g2 = rte_graph_create("worker2", &gconf);
716 [ - + ]: 1 : if (g2 == RTE_GRAPH_ID_INVALID) {
717 : 0 : printf("Graph 2 creation failed with error = %d\n", rte_errno);
718 : 0 : return -1;
719 : : }
720 : 1 : g3 = rte_graph_create("worker3", &gconf);
721 [ - + ]: 1 : if (g3 == RTE_GRAPH_ID_INVALID) {
722 : 0 : printf("Graph 3 creation failed with error = %d\n", rte_errno);
723 : 0 : return -1;
724 : : }
725 [ + - - + ]: 1 : if (g1 == g2 || g2 == g3 || g1 == g3) {
726 : : printf("Graph ids should be different\n");
727 : 0 : return -1;
728 : : }
729 [ - + ]: 1 : if (rte_graph_destroy(g2) < 0) {
730 : : printf("Graph 2 suppression failed\n");
731 : 0 : return -1;
732 : : }
733 : 1 : g4 = rte_graph_create("worker4", &gconf);
734 [ - + ]: 1 : if (g4 == RTE_GRAPH_ID_INVALID) {
735 : 0 : printf("Graph 4 creation failed with error = %d\n", rte_errno);
736 : 0 : return -1;
737 : : }
738 [ + - - + ]: 1 : if (g1 == g3 || g1 == g4 || g3 == g4) {
739 : : printf("Graph ids should be different\n");
740 : 0 : return -1;
741 : : }
742 : 1 : g2 = rte_graph_clone(g1, "worker2", &gconf);
743 [ - + ]: 1 : if (g2 == RTE_GRAPH_ID_INVALID) {
744 : 0 : printf("Graph 4 creation failed with error = %d\n", rte_errno);
745 : 0 : return -1;
746 : : }
747 [ + - + - : 1 : if (g1 == g2 || g1 == g3 || g1 == g4 || g2 == g3 || g2 == g4 || g3 == g4) {
- + ]
748 : : printf("Graph ids should be different\n");
749 : 0 : return -1;
750 : : }
751 [ - + ]: 1 : if (rte_graph_destroy(g1) < 0) {
752 : : printf("Graph 1 suppression failed\n");
753 : 0 : return -1;
754 : : }
755 [ - + ]: 1 : if (rte_graph_destroy(g2) < 0) {
756 : : printf("Graph 2 suppression failed\n");
757 : 0 : return -1;
758 : : }
759 [ - + ]: 1 : if (rte_graph_destroy(g3) < 0) {
760 : : printf("Graph 3 suppression failed\n");
761 : 0 : return -1;
762 : : }
763 [ - + ]: 1 : if (rte_graph_destroy(g4) < 0) {
764 : : printf("Graph 4 suppression failed\n");
765 : 0 : return -1;
766 : : }
767 : : return 0;
768 : : }
769 : :
770 : : static int
771 : 1 : test_graph_model_mcore_dispatch_node_lcore_affinity_set(void)
772 : : {
773 : : rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID;
774 : : unsigned int worker_lcore = RTE_MAX_LCORE;
775 : 1 : struct rte_graph_param graph_conf = {0};
776 : : rte_node_t nid = RTE_NODE_ID_INVALID;
777 : 1 : char node_name[64] = "test_node00";
778 : : struct rte_node *node;
779 : : int ret = 0;
780 : :
781 : 1 : worker_lcore = rte_get_next_lcore(worker_lcore, true, 1);
782 : 1 : ret = rte_graph_model_mcore_dispatch_node_lcore_affinity_set(node_name, worker_lcore);
783 [ + - ]: 1 : if (ret == 0)
784 : : printf("Set node %s affinity to lcore %u\n", node_name, worker_lcore);
785 : :
786 : 1 : nid = rte_node_from_name(node_name);
787 : 1 : cloned_graph_id = rte_graph_clone(graph_id, "cloned-test1", &graph_conf);
788 : 1 : node = rte_graph_node_get(cloned_graph_id, nid);
789 : :
790 [ - + ]: 1 : if (node->dispatch.lcore_id != worker_lcore) {
791 : : printf("set node affinity failed\n");
792 : : ret = -1;
793 : : }
794 : :
795 : 1 : rte_graph_destroy(cloned_graph_id);
796 : :
797 : 1 : return ret;
798 : : }
799 : :
800 : : static int
801 : 1 : test_graph_model_mcore_dispatch_core_bind_unbind(void)
802 : : {
803 : : rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID;
804 : : unsigned int worker_lcore = RTE_MAX_LCORE;
805 : 1 : struct rte_graph_param graph_conf = {0};
806 : : struct rte_graph *graph;
807 : : int ret = 0;
808 : :
809 : 1 : worker_lcore = rte_get_next_lcore(worker_lcore, true, 1);
810 : 1 : cloned_graph_id = rte_graph_clone(graph_id, "cloned-test2", &graph_conf);
811 : :
812 : 1 : ret = rte_graph_worker_model_set(RTE_GRAPH_MODEL_MCORE_DISPATCH);
813 [ - + ]: 1 : if (ret != 0) {
814 : : printf("Set graph mcore dispatch model failed\n");
815 : 0 : goto fail;
816 : : }
817 : :
818 : 1 : ret = rte_graph_model_mcore_dispatch_core_bind(cloned_graph_id, worker_lcore);
819 [ - + ]: 1 : if (ret != 0) {
820 : 0 : printf("bind graph %d to lcore %u failed\n", graph_id, worker_lcore);
821 : 0 : goto fail;
822 : : }
823 : :
824 : 1 : graph = rte_graph_lookup("worker0-cloned-test2");
825 : :
826 [ - + ]: 1 : if (graph->dispatch.lcore_id != worker_lcore) {
827 : 0 : printf("bind graph %s(id:%d) with lcore %u failed\n",
828 : 0 : graph->name, graph->id, worker_lcore);
829 : : ret = -1;
830 : 0 : goto fail;
831 : : }
832 : :
833 : 1 : rte_graph_model_mcore_dispatch_core_unbind(cloned_graph_id);
834 [ + - ]: 1 : if (graph->dispatch.lcore_id != RTE_MAX_LCORE) {
835 : 0 : printf("unbind graph %s(id:%d) failed %d\n",
836 : 0 : graph->name, graph->id, graph->dispatch.lcore_id);
837 : : ret = -1;
838 : : }
839 : :
840 : 1 : fail:
841 : 1 : rte_graph_destroy(cloned_graph_id);
842 : :
843 : 1 : return ret;
844 : : }
845 : :
846 : : static int
847 : 1 : test_graph_worker_model_set_get(void)
848 : : {
849 : : rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID;
850 : 1 : struct rte_graph_param graph_conf = {0};
851 : : struct rte_graph *graph;
852 : : int ret = 0;
853 : :
854 : 1 : cloned_graph_id = rte_graph_clone(graph_id, "cloned-test3", &graph_conf);
855 : 1 : ret = rte_graph_worker_model_set(RTE_GRAPH_MODEL_MCORE_DISPATCH);
856 [ - + ]: 1 : if (ret != 0) {
857 : : printf("Set graph mcore dispatch model failed\n");
858 : 0 : goto fail;
859 : : }
860 : :
861 : 1 : graph = rte_graph_lookup("worker0-cloned-test3");
862 [ + - ]: 1 : if (rte_graph_worker_model_get(graph) != RTE_GRAPH_MODEL_MCORE_DISPATCH) {
863 : : printf("Get graph worker model failed\n");
864 : : ret = -1;
865 : : }
866 : :
867 : 1 : fail:
868 : 1 : rte_graph_destroy(cloned_graph_id);
869 : :
870 : 1 : return ret;
871 : : }
872 : :
873 : : static int
874 : 1 : test_graph_walk(void)
875 : : {
876 : 1 : struct rte_graph *graph = rte_graph_lookup("worker0");
877 : : int i;
878 : :
879 [ - + ]: 1 : if (!graph) {
880 : : printf("Graph lookup failed\n");
881 : 0 : return -1;
882 : : }
883 : :
884 [ + + ]: 6 : for (i = 0; i < 5; i++)
885 : 5 : rte_graph_walk(graph);
886 : : return 0;
887 : : }
888 : :
889 : : static int
890 : 1 : test_graph_lookup_functions(void)
891 : : {
892 : : test_main_t *tm = &test_main;
893 : : struct rte_node *node;
894 : : int i;
895 : :
896 [ + + ]: 5 : for (i = 0; i < MAX_NODES; i++) {
897 : 4 : node = rte_graph_node_get(graph_id, tm->test_node[i].idx);
898 [ - + ]: 4 : if (!node) {
899 : 0 : printf("rte_graph_node_get, failed for node = %d\n",
900 : : tm->test_node[i].idx);
901 : 0 : return -1;
902 : : }
903 : :
904 [ - + ]: 4 : if (tm->test_node[i].idx != node->id) {
905 : : printf("Node id didn't match, expected = %d got = %d\n",
906 : : tm->test_node[i].idx, node->id);
907 : 0 : return 0;
908 : : }
909 : :
910 [ - + ]: 4 : if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
911 : : printf("Node name didn't match, expected = %s got %s\n",
912 : : node_names[i], node->name);
913 : 0 : return -1;
914 : : }
915 : : }
916 : :
917 [ + + ]: 5 : for (i = 0; i < MAX_NODES; i++) {
918 : 4 : node = rte_graph_node_get_by_name("worker0", node_names[i]);
919 [ - + ]: 4 : if (!node) {
920 : 0 : printf("rte_graph_node_get, failed for node = %d\n",
921 : : tm->test_node[i].idx);
922 : 0 : return -1;
923 : : }
924 : :
925 [ - + ]: 4 : if (tm->test_node[i].idx != node->id) {
926 : : printf("Node id didn't match, expected = %d got = %d\n",
927 : : tm->test_node[i].idx, node->id);
928 : 0 : return 0;
929 : : }
930 : :
931 [ - + ]: 4 : if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
932 : : printf("Node name didn't match, expected = %s got %s\n",
933 : : node_names[i], node->name);
934 : 0 : return -1;
935 : : }
936 : : }
937 : :
938 : : return 0;
939 : : }
940 : :
941 : : static int
942 : 5 : graph_cluster_stats_cb_t(bool is_first, bool is_last, void *cookie,
943 : : const struct rte_graph_cluster_node_stats *st)
944 : : {
945 : : int i;
946 : :
947 : : RTE_SET_USED(is_first);
948 : : RTE_SET_USED(is_last);
949 : : RTE_SET_USED(cookie);
950 : :
951 [ + + ]: 30 : for (i = 0; i < MAX_NODES + 1; i++) {
952 : 25 : rte_node_t id = rte_node_from_name(node_patterns[i]);
953 [ + + ]: 25 : if (id == st->id) {
954 [ - + ]: 5 : if (obj_stats[i] != st->objs) {
955 : 0 : printf("Obj count miss match for node = %s expected = %"PRId64", got=%"PRId64"\n",
956 : : node_patterns[i], obj_stats[i],
957 : : st->objs);
958 : 0 : return -1;
959 : : }
960 : :
961 [ - + ]: 5 : if (fn_calls[i] != st->calls) {
962 : 0 : printf("Func call miss match for node = %s expected = %"PRId64", got = %"PRId64"\n",
963 : : node_patterns[i], fn_calls[i],
964 : : st->calls);
965 : 0 : return -1;
966 : : }
967 : : }
968 : : }
969 : : return 0;
970 : : }
971 : :
972 : : static int
973 : 1 : test_print_stats(void)
974 : : {
975 : : struct rte_graph_cluster_stats_param s_param;
976 : : struct rte_graph_cluster_stats *stats;
977 : 1 : const char *pattern = "worker0";
978 : :
979 : : if (!rte_graph_has_stats_feature())
980 : : return 0;
981 : :
982 : : /* Prepare stats object */
983 : : memset(&s_param, 0, sizeof(s_param));
984 : 1 : s_param.f = stdout;
985 : 1 : s_param.socket_id = SOCKET_ID_ANY;
986 : 1 : s_param.graph_patterns = &pattern;
987 : 1 : s_param.nb_graph_patterns = 1;
988 : 1 : s_param.fn = graph_cluster_stats_cb_t;
989 : :
990 : 1 : stats = rte_graph_cluster_stats_create(&s_param);
991 [ - + ]: 1 : if (stats == NULL) {
992 : : printf("Unable to get stats\n");
993 : 0 : return -1;
994 : : }
995 : : /* Clear screen and move to top left */
996 : 1 : rte_graph_cluster_stats_get(stats, 0);
997 : 1 : rte_graph_cluster_stats_destroy(stats);
998 : :
999 : 1 : return 0;
1000 : : }
1001 : :
1002 : : static int
1003 : 1 : graph_setup(void)
1004 : : {
1005 : : int i, j;
1006 : :
1007 : : static const struct rte_mbuf_dynfield graph_dynfield_desc = {
1008 : : .name = "test_graph_dynfield",
1009 : : .size = sizeof(graph_dynfield_t),
1010 : : .align = alignof(graph_dynfield_t),
1011 : : };
1012 : 1 : graph_dynfield_offset =
1013 : 1 : rte_mbuf_dynfield_register(&graph_dynfield_desc);
1014 [ - + ]: 1 : if (graph_dynfield_offset < 0) {
1015 : : printf("Cannot register mbuf field\n");
1016 : 0 : return TEST_FAILED;
1017 : : }
1018 : :
1019 [ + + ]: 6 : for (i = 0; i <= MAX_NODES; i++) {
1020 [ + + ]: 2565 : for (j = 0; j < MBUFF_SIZE; j++)
1021 : 2560 : mbuf_p[i][j] = &mbuf[i][j];
1022 : : }
1023 [ - + ]: 1 : if (test_node_clone()) {
1024 : : printf("test_node_clone: fail\n");
1025 : 0 : return -1;
1026 : : }
1027 : : printf("test_node_clone: pass\n");
1028 : :
1029 : 1 : return 0;
1030 : : }
1031 : :
1032 : : static void
1033 : 1 : graph_teardown(void)
1034 : : {
1035 : : int id;
1036 : :
1037 : 1 : id = rte_graph_destroy(rte_graph_from_name("worker0"));
1038 [ - + ]: 1 : if (id)
1039 : : printf("Graph Destroy failed\n");
1040 : 1 : }
1041 : :
1042 : : static struct unit_test_suite graph_testsuite = {
1043 : : .suite_name = "Graph library test suite",
1044 : : .setup = graph_setup,
1045 : : .teardown = graph_teardown,
1046 : : .unit_test_cases = {
1047 : : TEST_CASE(test_update_edges),
1048 : : TEST_CASE(test_lookup_functions),
1049 : : TEST_CASE(test_create_graph),
1050 : : TEST_CASE(test_graph_clone),
1051 : : TEST_CASE(test_graph_id_collisions),
1052 : : TEST_CASE(test_graph_model_mcore_dispatch_node_lcore_affinity_set),
1053 : : TEST_CASE(test_graph_model_mcore_dispatch_core_bind_unbind),
1054 : : TEST_CASE(test_graph_worker_model_set_get),
1055 : : TEST_CASE(test_graph_lookup_functions),
1056 : : TEST_CASE(test_graph_walk),
1057 : : TEST_CASE(test_print_stats),
1058 : : TEST_CASES_END(), /**< NULL terminate unit test array */
1059 : : },
1060 : : };
1061 : :
1062 : : static int
1063 : 1 : graph_autotest_fn(void)
1064 : : {
1065 : 1 : return unit_test_suite_runner(&graph_testsuite);
1066 : : }
1067 : :
1068 : 251 : REGISTER_FAST_TEST(graph_autotest, true, true, graph_autotest_fn);
1069 : :
1070 : : static int
1071 : 1 : test_node_list_dump(void)
1072 : : {
1073 : 1 : rte_node_list_dump(stdout);
1074 : :
1075 : 1 : return TEST_SUCCESS;
1076 : : }
1077 : :
1078 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
1079 : :
1080 : 251 : REGISTER_FAST_TEST(node_list_dump, true, true, test_node_list_dump);
|