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