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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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