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