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_clone(void) 665 { 666 rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID; 667 rte_graph_t main_graph_id = RTE_GRAPH_ID_INVALID; 668 struct rte_graph_param graph_conf = {0}; 669 int ret = 0; 670 671 main_graph_id = rte_graph_from_name("worker0"); 672 if (main_graph_id == RTE_GRAPH_ID_INVALID) { 673 printf("Must create main graph first\n"); 674 ret = -1; 675 } 676 677 graph_conf.dispatch.mp_capacity = 1024; 678 graph_conf.dispatch.wq_size_max = 32; 679 680 cloned_graph_id = rte_graph_clone(main_graph_id, "cloned-test0", &graph_conf); 681 682 if (cloned_graph_id == RTE_GRAPH_ID_INVALID) { 683 printf("Graph creation failed with error = %d\n", rte_errno); 684 ret = -1; 685 } 686 687 if (strcmp(rte_graph_id_to_name(cloned_graph_id), "worker0-cloned-test0")) { 688 printf("Cloned graph should name as %s but get %s\n", "worker0-cloned-test", 689 rte_graph_id_to_name(cloned_graph_id)); 690 ret = -1; 691 } 692 693 rte_graph_destroy(cloned_graph_id); 694 695 return ret; 696 } 697 698 static int 699 test_graph_model_mcore_dispatch_node_lcore_affinity_set(void) 700 { 701 rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID; 702 unsigned int worker_lcore = RTE_MAX_LCORE; 703 struct rte_graph_param graph_conf = {0}; 704 rte_node_t nid = RTE_NODE_ID_INVALID; 705 char node_name[64] = "test_node00"; 706 struct rte_node *node; 707 int ret = 0; 708 709 worker_lcore = rte_get_next_lcore(worker_lcore, true, 1); 710 ret = rte_graph_model_mcore_dispatch_node_lcore_affinity_set(node_name, worker_lcore); 711 if (ret == 0) 712 printf("Set node %s affinity to lcore %u\n", node_name, worker_lcore); 713 714 nid = rte_node_from_name(node_name); 715 cloned_graph_id = rte_graph_clone(graph_id, "cloned-test1", &graph_conf); 716 node = rte_graph_node_get(cloned_graph_id, nid); 717 718 if (node->dispatch.lcore_id != worker_lcore) { 719 printf("set node affinity failed\n"); 720 ret = -1; 721 } 722 723 rte_graph_destroy(cloned_graph_id); 724 725 return ret; 726 } 727 728 static int 729 test_graph_model_mcore_dispatch_core_bind_unbind(void) 730 { 731 rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID; 732 unsigned int worker_lcore = RTE_MAX_LCORE; 733 struct rte_graph_param graph_conf = {0}; 734 struct rte_graph *graph; 735 int ret = 0; 736 737 worker_lcore = rte_get_next_lcore(worker_lcore, true, 1); 738 cloned_graph_id = rte_graph_clone(graph_id, "cloned-test2", &graph_conf); 739 740 ret = rte_graph_worker_model_set(RTE_GRAPH_MODEL_MCORE_DISPATCH); 741 if (ret != 0) { 742 printf("Set graph mcore dispatch model failed\n"); 743 ret = -1; 744 } 745 746 ret = rte_graph_model_mcore_dispatch_core_bind(cloned_graph_id, worker_lcore); 747 if (ret != 0) { 748 printf("bind graph %d to lcore %u failed\n", graph_id, worker_lcore); 749 ret = -1; 750 } 751 752 graph = rte_graph_lookup("worker0-cloned-test2"); 753 754 if (graph->dispatch.lcore_id != worker_lcore) { 755 printf("bind graph %s(id:%d) with lcore %u failed\n", 756 graph->name, graph->id, worker_lcore); 757 ret = -1; 758 } 759 760 rte_graph_model_mcore_dispatch_core_unbind(cloned_graph_id); 761 if (graph->dispatch.lcore_id != RTE_MAX_LCORE) { 762 printf("unbind graph %s(id:%d) failed %d\n", 763 graph->name, graph->id, graph->dispatch.lcore_id); 764 ret = -1; 765 } 766 767 rte_graph_destroy(cloned_graph_id); 768 769 return ret; 770 } 771 772 static int 773 test_graph_worker_model_set_get(void) 774 { 775 rte_graph_t cloned_graph_id = RTE_GRAPH_ID_INVALID; 776 struct rte_graph_param graph_conf = {0}; 777 struct rte_graph *graph; 778 int ret = 0; 779 780 cloned_graph_id = rte_graph_clone(graph_id, "cloned-test3", &graph_conf); 781 ret = rte_graph_worker_model_set(RTE_GRAPH_MODEL_MCORE_DISPATCH); 782 if (ret != 0) { 783 printf("Set graph mcore dispatch model failed\n"); 784 ret = -1; 785 } 786 787 graph = rte_graph_lookup("worker0-cloned-test3"); 788 if (rte_graph_worker_model_get(graph) != RTE_GRAPH_MODEL_MCORE_DISPATCH) { 789 printf("Get graph worker model failed\n"); 790 ret = -1; 791 } 792 793 rte_graph_destroy(cloned_graph_id); 794 795 return 0; 796 } 797 798 static int 799 test_graph_walk(void) 800 { 801 struct rte_graph *graph = rte_graph_lookup("worker0"); 802 int i; 803 804 if (!graph) { 805 printf("Graph lookup failed\n"); 806 return -1; 807 } 808 809 for (i = 0; i < 5; i++) 810 rte_graph_walk(graph); 811 return 0; 812 } 813 814 static int 815 test_graph_lookup_functions(void) 816 { 817 test_main_t *tm = &test_main; 818 struct rte_node *node; 819 int i; 820 821 for (i = 0; i < MAX_NODES; i++) { 822 node = rte_graph_node_get(graph_id, tm->test_node[i].idx); 823 if (!node) { 824 printf("rte_graph_node_get, failed for node = %d\n", 825 tm->test_node[i].idx); 826 return -1; 827 } 828 829 if (tm->test_node[i].idx != node->id) { 830 printf("Node id didn't match, expected = %d got = %d\n", 831 tm->test_node[i].idx, node->id); 832 return 0; 833 } 834 835 if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) { 836 printf("Node name didn't match, expected = %s got %s\n", 837 node_names[i], node->name); 838 return -1; 839 } 840 } 841 842 for (i = 0; i < MAX_NODES; i++) { 843 node = rte_graph_node_get_by_name("worker0", node_names[i]); 844 if (!node) { 845 printf("rte_graph_node_get, failed for node = %d\n", 846 tm->test_node[i].idx); 847 return -1; 848 } 849 850 if (tm->test_node[i].idx != node->id) { 851 printf("Node id didn't match, expected = %d got = %d\n", 852 tm->test_node[i].idx, node->id); 853 return 0; 854 } 855 856 if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) { 857 printf("Node name didn't match, expected = %s got %s\n", 858 node_names[i], node->name); 859 return -1; 860 } 861 } 862 863 return 0; 864 } 865 866 static int 867 graph_cluster_stats_cb_t(bool is_first, bool is_last, void *cookie, 868 const struct rte_graph_cluster_node_stats *st) 869 { 870 int i; 871 872 RTE_SET_USED(is_first); 873 RTE_SET_USED(is_last); 874 RTE_SET_USED(cookie); 875 876 for (i = 0; i < MAX_NODES + 1; i++) { 877 rte_node_t id = rte_node_from_name(node_patterns[i]); 878 if (id == st->id) { 879 if (obj_stats[i] != st->objs) { 880 printf("Obj count miss match for node = %s expected = %"PRId64", got=%"PRId64"\n", 881 node_patterns[i], obj_stats[i], 882 st->objs); 883 return -1; 884 } 885 886 if (fn_calls[i] != st->calls) { 887 printf("Func call miss match for node = %s expected = %"PRId64", got = %"PRId64"\n", 888 node_patterns[i], fn_calls[i], 889 st->calls); 890 return -1; 891 } 892 } 893 } 894 return 0; 895 } 896 897 static int 898 test_print_stats(void) 899 { 900 struct rte_graph_cluster_stats_param s_param; 901 struct rte_graph_cluster_stats *stats; 902 const char *pattern = "worker0"; 903 904 if (!rte_graph_has_stats_feature()) 905 return 0; 906 907 /* Prepare stats object */ 908 memset(&s_param, 0, sizeof(s_param)); 909 s_param.f = stdout; 910 s_param.socket_id = SOCKET_ID_ANY; 911 s_param.graph_patterns = &pattern; 912 s_param.nb_graph_patterns = 1; 913 s_param.fn = graph_cluster_stats_cb_t; 914 915 stats = rte_graph_cluster_stats_create(&s_param); 916 if (stats == NULL) { 917 printf("Unable to get stats\n"); 918 return -1; 919 } 920 /* Clear screen and move to top left */ 921 rte_graph_cluster_stats_get(stats, 0); 922 rte_graph_cluster_stats_destroy(stats); 923 924 return 0; 925 } 926 927 static int 928 graph_setup(void) 929 { 930 int i, j; 931 932 static const struct rte_mbuf_dynfield graph_dynfield_desc = { 933 .name = "test_graph_dynfield", 934 .size = sizeof(graph_dynfield_t), 935 .align = __alignof__(graph_dynfield_t), 936 }; 937 graph_dynfield_offset = 938 rte_mbuf_dynfield_register(&graph_dynfield_desc); 939 if (graph_dynfield_offset < 0) { 940 printf("Cannot register mbuf field\n"); 941 return TEST_FAILED; 942 } 943 944 for (i = 0; i <= MAX_NODES; i++) { 945 for (j = 0; j < MBUFF_SIZE; j++) 946 mbuf_p[i][j] = &mbuf[i][j]; 947 } 948 if (test_node_clone()) { 949 printf("test_node_clone: fail\n"); 950 return -1; 951 } 952 printf("test_node_clone: pass\n"); 953 954 return 0; 955 } 956 957 static void 958 graph_teardown(void) 959 { 960 int id; 961 962 id = rte_graph_destroy(rte_graph_from_name("worker0")); 963 if (id) 964 printf("Graph Destroy failed\n"); 965 } 966 967 static struct unit_test_suite graph_testsuite = { 968 .suite_name = "Graph library test suite", 969 .setup = graph_setup, 970 .teardown = graph_teardown, 971 .unit_test_cases = { 972 TEST_CASE(test_update_edges), 973 TEST_CASE(test_lookup_functions), 974 TEST_CASE(test_create_graph), 975 TEST_CASE(test_graph_clone), 976 TEST_CASE(test_graph_model_mcore_dispatch_node_lcore_affinity_set), 977 TEST_CASE(test_graph_model_mcore_dispatch_core_bind_unbind), 978 TEST_CASE(test_graph_worker_model_set_get), 979 TEST_CASE(test_graph_lookup_functions), 980 TEST_CASE(test_graph_walk), 981 TEST_CASE(test_print_stats), 982 TEST_CASES_END(), /**< NULL terminate unit test array */ 983 }, 984 }; 985 986 static int 987 graph_autotest_fn(void) 988 { 989 return unit_test_suite_runner(&graph_testsuite); 990 } 991 992 REGISTER_FAST_TEST(graph_autotest, true, true, graph_autotest_fn); 993 994 static int 995 test_node_list_dump(void) 996 { 997 rte_node_list_dump(stdout); 998 999 return TEST_SUCCESS; 1000 } 1001 1002 #endif /* !RTE_EXEC_ENV_WINDOWS */ 1003 1004 REGISTER_FAST_TEST(node_list_dump, true, true, test_node_list_dump); 1005