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 /* Clone with same name, should fail */ 554 dummy_id = rte_node_clone(node_id, "test_node00"); 555 if (!rte_node_is_invalid(dummy_id)) { 556 printf("Got valid id when clone with same name, Expecting fail\n"); 557 return -1; 558 } 559 560 for (i = 1; i < MAX_NODES; i++) { 561 tm->test_node[i].idx = 562 rte_node_clone(node_id, tm->test_node[i].node.name); 563 if (rte_node_is_invalid(tm->test_node[i].idx)) { 564 printf("Got invalid node id\n"); 565 return -1; 566 } 567 } 568 569 /* Clone from cloned node should fail */ 570 dummy_id = rte_node_clone(tm->test_node[1].idx, "dummy_node"); 571 if (!rte_node_is_invalid(dummy_id)) { 572 printf("Got valid node id when cloning from cloned node, expected fail\n"); 573 return -1; 574 } 575 576 return 0; 577 } 578 579 static int 580 test_update_edges(void) 581 { 582 test_main_t *tm = &test_main; 583 uint32_t node_id; 584 uint16_t count; 585 int i; 586 587 node_id = rte_node_from_name("test_node00"); 588 count = rte_node_edge_update(node_id, 0, 589 tm->test_node[0].node.next_nodes, 590 tm->test_node[0].node.nb_edges); 591 if (count != tm->test_node[0].node.nb_edges) { 592 printf("Update edges failed expected: %d got = %d\n", 593 tm->test_node[0].node.nb_edges, count); 594 return -1; 595 } 596 597 for (i = 1; i < MAX_NODES; i++) { 598 count = rte_node_edge_update(tm->test_node[i].idx, 0, 599 tm->test_node[i].node.next_nodes, 600 tm->test_node[i].node.nb_edges); 601 if (count != tm->test_node[i].node.nb_edges) { 602 printf("Update edges failed expected: %d got = %d\n", 603 tm->test_node[i].node.nb_edges, count); 604 return -1; 605 } 606 607 count = rte_node_edge_shrink(tm->test_node[i].idx, 608 tm->test_node[i].node.nb_edges); 609 if (count != tm->test_node[i].node.nb_edges) { 610 printf("Shrink edges failed\n"); 611 return -1; 612 } 613 } 614 615 return 0; 616 } 617 618 static int 619 test_create_graph(void) 620 { 621 static const char *node_patterns_dummy[] = { 622 "test_node_source1", "test_node00", 623 "test_node00-test_node11", "test_node00-test_node22", 624 "test_node00-test_node33", "test_node00-dummy_node", 625 }; 626 struct rte_graph_param gconf = { 627 .socket_id = SOCKET_ID_ANY, 628 .nb_node_patterns = 6, 629 .node_patterns = node_patterns_dummy, 630 }; 631 uint32_t dummy_node_id; 632 uint32_t node_id; 633 634 node_id = rte_node_from_name("test_node00"); 635 dummy_node_id = rte_node_clone(node_id, "dummy_node"); 636 if (rte_node_is_invalid(dummy_node_id)) { 637 printf("Got invalid node id\n"); 638 return -1; 639 } 640 641 graph_id = rte_graph_create("worker0", &gconf); 642 if (graph_id != RTE_GRAPH_ID_INVALID) { 643 printf("Graph creation success with isolated node, expected graph creation fail\n"); 644 return -1; 645 } 646 647 gconf.nb_node_patterns = 5; 648 gconf.node_patterns = node_patterns; 649 graph_id = rte_graph_create("worker0", &gconf); 650 if (graph_id == RTE_GRAPH_ID_INVALID) { 651 printf("Graph creation failed with error = %d\n", rte_errno); 652 return -1; 653 } 654 return 0; 655 } 656 657 static int 658 test_graph_walk(void) 659 { 660 struct rte_graph *graph = rte_graph_lookup("worker0"); 661 int i; 662 663 if (!graph) { 664 printf("Graph lookup failed\n"); 665 return -1; 666 } 667 668 for (i = 0; i < 5; i++) 669 rte_graph_walk(graph); 670 return 0; 671 } 672 673 static int 674 test_graph_lookup_functions(void) 675 { 676 test_main_t *tm = &test_main; 677 struct rte_node *node; 678 int i; 679 680 for (i = 0; i < MAX_NODES; i++) { 681 node = rte_graph_node_get(graph_id, tm->test_node[i].idx); 682 if (!node) { 683 printf("rte_graph_node_get, failed for node = %d\n", 684 tm->test_node[i].idx); 685 return -1; 686 } 687 688 if (tm->test_node[i].idx != node->id) { 689 printf("Node id didn't match, expected = %d got = %d\n", 690 tm->test_node[i].idx, node->id); 691 return 0; 692 } 693 694 if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) { 695 printf("Node name didn't match, expected = %s got %s\n", 696 node_names[i], node->name); 697 return -1; 698 } 699 } 700 701 for (i = 0; i < MAX_NODES; i++) { 702 node = rte_graph_node_get_by_name("worker0", node_names[i]); 703 if (!node) { 704 printf("rte_graph_node_get, failed for node = %d\n", 705 tm->test_node[i].idx); 706 return -1; 707 } 708 709 if (tm->test_node[i].idx != node->id) { 710 printf("Node id didn't match, expected = %d got = %d\n", 711 tm->test_node[i].idx, node->id); 712 return 0; 713 } 714 715 if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) { 716 printf("Node name didn't match, expected = %s got %s\n", 717 node_names[i], node->name); 718 return -1; 719 } 720 } 721 722 return 0; 723 } 724 725 static int 726 graph_cluster_stats_cb_t(bool is_first, bool is_last, void *cookie, 727 const struct rte_graph_cluster_node_stats *st) 728 { 729 int i; 730 731 RTE_SET_USED(is_first); 732 RTE_SET_USED(is_last); 733 RTE_SET_USED(cookie); 734 735 for (i = 0; i < MAX_NODES + 1; i++) { 736 rte_node_t id = rte_node_from_name(node_patterns[i]); 737 if (id == st->id) { 738 if (obj_stats[i] != st->objs) { 739 printf("Obj count miss match for node = %s expected = %"PRId64", got=%"PRId64"\n", 740 node_patterns[i], obj_stats[i], 741 st->objs); 742 return -1; 743 } 744 745 if (fn_calls[i] != st->calls) { 746 printf("Func call miss match for node = %s expected = %"PRId64", got = %"PRId64"\n", 747 node_patterns[i], fn_calls[i], 748 st->calls); 749 return -1; 750 } 751 } 752 } 753 return 0; 754 } 755 756 static int 757 test_print_stats(void) 758 { 759 struct rte_graph_cluster_stats_param s_param; 760 struct rte_graph_cluster_stats *stats; 761 const char *pattern = "worker0"; 762 763 if (!rte_graph_has_stats_feature()) 764 return 0; 765 766 /* Prepare stats object */ 767 memset(&s_param, 0, sizeof(s_param)); 768 s_param.f = stdout; 769 s_param.socket_id = SOCKET_ID_ANY; 770 s_param.graph_patterns = &pattern; 771 s_param.nb_graph_patterns = 1; 772 s_param.fn = graph_cluster_stats_cb_t; 773 774 stats = rte_graph_cluster_stats_create(&s_param); 775 if (stats == NULL) { 776 printf("Unable to get stats\n"); 777 return -1; 778 } 779 /* Clear screen and move to top left */ 780 rte_graph_cluster_stats_get(stats, 0); 781 rte_graph_cluster_stats_destroy(stats); 782 783 return 0; 784 } 785 786 static int 787 graph_setup(void) 788 { 789 int i, j; 790 791 static const struct rte_mbuf_dynfield graph_dynfield_desc = { 792 .name = "test_graph_dynfield", 793 .size = sizeof(graph_dynfield_t), 794 .align = __alignof__(graph_dynfield_t), 795 }; 796 graph_dynfield_offset = 797 rte_mbuf_dynfield_register(&graph_dynfield_desc); 798 if (graph_dynfield_offset < 0) { 799 printf("Cannot register mbuf field\n"); 800 return TEST_FAILED; 801 } 802 803 for (i = 0; i <= MAX_NODES; i++) { 804 for (j = 0; j < MBUFF_SIZE; j++) 805 mbuf_p[i][j] = &mbuf[i][j]; 806 } 807 if (test_node_clone()) { 808 printf("test_node_clone: fail\n"); 809 return -1; 810 } 811 printf("test_node_clone: pass\n"); 812 813 return 0; 814 } 815 816 static void 817 graph_teardown(void) 818 { 819 int id; 820 821 id = rte_graph_destroy(rte_graph_from_name("worker0")); 822 if (id) 823 printf("Graph Destroy failed\n"); 824 } 825 826 static struct unit_test_suite graph_testsuite = { 827 .suite_name = "Graph library test suite", 828 .setup = graph_setup, 829 .teardown = graph_teardown, 830 .unit_test_cases = { 831 TEST_CASE(test_update_edges), 832 TEST_CASE(test_lookup_functions), 833 TEST_CASE(test_create_graph), 834 TEST_CASE(test_graph_lookup_functions), 835 TEST_CASE(test_graph_walk), 836 TEST_CASE(test_print_stats), 837 TEST_CASES_END(), /**< NULL terminate unit test array */ 838 }, 839 }; 840 841 static int 842 graph_autotest_fn(void) 843 { 844 return unit_test_suite_runner(&graph_testsuite); 845 } 846 847 REGISTER_TEST_COMMAND(graph_autotest, graph_autotest_fn); 848 849 static int 850 test_node_list_dump(void) 851 { 852 rte_node_list_dump(stdout); 853 854 return TEST_SUCCESS; 855 } 856 857 #endif /* !RTE_EXEC_ENV_WINDOWS */ 858 859 REGISTER_TEST_COMMAND(node_list_dump, test_node_list_dump); 860