1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(C) 2020 Marvell International Ltd. 3 */ 4 5 #ifndef _RTE_GRAPH_H_ 6 #define _RTE_GRAPH_H_ 7 8 /** 9 * @file rte_graph.h 10 * 11 * @warning 12 * @b EXPERIMENTAL: 13 * All functions in this file may be changed or removed without prior notice. 14 * 15 * Graph architecture abstracts the data processing functions as 16 * "node" and "link" them together to create a complex "graph" to enable 17 * reusable/modular data processing functions. 18 * 19 * This API enables graph framework operations such as create, lookup, 20 * dump and destroy on graph and node operations such as clone, 21 * edge update, and edge shrink, etc. The API also allows to create the stats 22 * cluster to monitor per graph and per node stats. 23 * 24 */ 25 26 #include <stdbool.h> 27 #include <stdio.h> 28 29 #include <rte_common.h> 30 #include <rte_compat.h> 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 #define RTE_GRAPH_NAMESIZE 64 /**< Max length of graph name. */ 37 #define RTE_NODE_NAMESIZE 64 /**< Max length of node name. */ 38 #define RTE_GRAPH_PCAP_FILE_SZ 64 /**< Max length of pcap file name. */ 39 #define RTE_GRAPH_OFF_INVALID UINT32_MAX /**< Invalid graph offset. */ 40 #define RTE_NODE_ID_INVALID UINT32_MAX /**< Invalid node id. */ 41 #define RTE_EDGE_ID_INVALID UINT16_MAX /**< Invalid edge id. */ 42 #define RTE_GRAPH_ID_INVALID UINT16_MAX /**< Invalid graph id. */ 43 #define RTE_GRAPH_FENCE 0xdeadbeef12345678ULL /**< Graph fence data. */ 44 45 typedef uint32_t rte_graph_off_t; /**< Graph offset type. */ 46 typedef uint32_t rte_node_t; /**< Node id type. */ 47 typedef uint16_t rte_edge_t; /**< Edge id type. */ 48 typedef uint16_t rte_graph_t; /**< Graph id type. */ 49 50 /** Burst size in terms of log2 */ 51 #if RTE_GRAPH_BURST_SIZE == 1 52 #define RTE_GRAPH_BURST_SIZE_LOG2 0 /**< Object burst size of 1. */ 53 #elif RTE_GRAPH_BURST_SIZE == 2 54 #define RTE_GRAPH_BURST_SIZE_LOG2 1 /**< Object burst size of 2. */ 55 #elif RTE_GRAPH_BURST_SIZE == 4 56 #define RTE_GRAPH_BURST_SIZE_LOG2 2 /**< Object burst size of 4. */ 57 #elif RTE_GRAPH_BURST_SIZE == 8 58 #define RTE_GRAPH_BURST_SIZE_LOG2 3 /**< Object burst size of 8. */ 59 #elif RTE_GRAPH_BURST_SIZE == 16 60 #define RTE_GRAPH_BURST_SIZE_LOG2 4 /**< Object burst size of 16. */ 61 #elif RTE_GRAPH_BURST_SIZE == 32 62 #define RTE_GRAPH_BURST_SIZE_LOG2 5 /**< Object burst size of 32. */ 63 #elif RTE_GRAPH_BURST_SIZE == 64 64 #define RTE_GRAPH_BURST_SIZE_LOG2 6 /**< Object burst size of 64. */ 65 #elif RTE_GRAPH_BURST_SIZE == 128 66 #define RTE_GRAPH_BURST_SIZE_LOG2 7 /**< Object burst size of 128. */ 67 #elif RTE_GRAPH_BURST_SIZE == 256 68 #define RTE_GRAPH_BURST_SIZE_LOG2 8 /**< Object burst size of 256. */ 69 #else 70 #error "Unsupported burst size" 71 #endif 72 73 /* Forward declaration */ 74 struct rte_node; /**< Node object */ 75 struct rte_graph; /**< Graph object */ 76 struct rte_graph_cluster_stats; /**< Stats for Cluster of graphs */ 77 struct rte_graph_cluster_node_stats; /**< Node stats within cluster of graphs */ 78 79 /** 80 * Node process function. 81 * 82 * The function invoked when the worker thread walks on nodes using 83 * rte_graph_walk(). 84 * 85 * @param graph 86 * Pointer to the graph object. 87 * @param node 88 * Pointer to the node object. 89 * @param objs 90 * Pointer to an array of objects to be processed. 91 * @param nb_objs 92 * Number of objects in the array. 93 * 94 * @return 95 * Number of objects processed. 96 * 97 * @see rte_graph_walk() 98 * 99 */ 100 typedef uint16_t (*rte_node_process_t)(struct rte_graph *graph, 101 struct rte_node *node, void **objs, 102 uint16_t nb_objs); 103 104 /** 105 * Node initialization function. 106 * 107 * The function invoked when the user creates the graph using rte_graph_create() 108 * 109 * @param graph 110 * Pointer to the graph object. 111 * @param node 112 * Pointer to the node object. 113 * 114 * @return 115 * - 0: Success. 116 * -<0: Failure. 117 * 118 * @see rte_graph_create() 119 */ 120 typedef int (*rte_node_init_t)(const struct rte_graph *graph, 121 struct rte_node *node); 122 123 /** 124 * Node finalization function. 125 * 126 * The function invoked when the user destroys the graph using 127 * rte_graph_destroy(). 128 * 129 * @param graph 130 * Pointer to the graph object. 131 * @param node 132 * Pointer to the node object. 133 * 134 * @see rte_graph_destroy() 135 */ 136 typedef void (*rte_node_fini_t)(const struct rte_graph *graph, 137 struct rte_node *node); 138 139 /** 140 * Graph cluster stats callback. 141 * 142 * @param is_first 143 * Flag to denote that stats are of the first node. 144 * @param is_last 145 * Flag to denote that stats are of the last node. 146 * @param cookie 147 * Cookie supplied during stats creation. 148 * @param stats 149 * Node cluster stats data. 150 * 151 * @return 152 * - 0: Success. 153 * -<0: Failure. 154 */ 155 typedef int (*rte_graph_cluster_stats_cb_t)(bool is_first, bool is_last, 156 void *cookie, const struct rte_graph_cluster_node_stats *stats); 157 158 /** 159 * Structure to hold configuration parameters for creating the graph. 160 * 161 * @see rte_graph_create() 162 */ 163 struct rte_graph_param { 164 int socket_id; /**< Socket id where memory is allocated. */ 165 uint16_t nb_node_patterns; /**< Number of node patterns. */ 166 const char **node_patterns; 167 /**< Array of node patterns based on shell pattern. */ 168 169 bool pcap_enable; /**< Pcap enable. */ 170 uint64_t num_pkt_to_capture; /**< Number of packets to capture. */ 171 char *pcap_filename; /**< Filename in which packets to be captured.*/ 172 173 RTE_STD_C11 174 union { 175 struct { 176 uint64_t rsvd; /**< Reserved for rtc model. */ 177 } rtc; 178 struct { 179 uint32_t wq_size_max; /**< Maximum size of workqueue for dispatch model. */ 180 uint32_t mp_capacity; /**< Capacity of memory pool for dispatch model. */ 181 } dispatch; 182 }; 183 }; 184 185 /** 186 * Structure to hold configuration parameters for graph cluster stats create. 187 * 188 * @see rte_graph_cluster_stats_create() 189 */ 190 struct rte_graph_cluster_stats_param { 191 int socket_id; 192 /**< Socket id where memory is allocated */ 193 rte_graph_cluster_stats_cb_t fn; 194 /**< Stats print callback function. NULL value allowed, in that case, 195 * default print stat function used. 196 */ 197 RTE_STD_C11 198 union { 199 void *cookie; 200 FILE *f; /**< File pointer to dump the stats when fn == NULL. */ 201 }; 202 uint16_t nb_graph_patterns; /**< Number of graph patterns. */ 203 const char **graph_patterns; 204 /**< Array of graph patterns based on shell pattern. */ 205 }; 206 207 /** 208 * Node cluster stats data structure. 209 * 210 * @see struct rte_graph_cluster_stats_param::fn 211 */ 212 struct rte_graph_cluster_node_stats { 213 uint64_t ts; /**< Current timestamp. */ 214 uint64_t calls; /**< Current number of calls made. */ 215 uint64_t objs; /**< Current number of objs processed. */ 216 uint64_t cycles; /**< Current number of cycles. */ 217 218 uint64_t prev_ts; /**< Previous call timestamp. */ 219 uint64_t prev_calls; /**< Previous number of calls. */ 220 uint64_t prev_objs; /**< Previous number of processed objs. */ 221 uint64_t prev_cycles; /**< Previous number of cycles. */ 222 223 RTE_STD_C11 224 union { 225 struct { 226 uint64_t sched_objs; 227 /**< Previous number of scheduled objs for dispatch model. */ 228 uint64_t sched_fail; 229 /**< Previous number of failed schedule objs for dispatch model. */ 230 } dispatch; 231 }; 232 233 uint64_t realloc_count; /**< Realloc count. */ 234 235 rte_node_t id; /**< Node identifier of stats. */ 236 uint64_t hz; /**< Cycles per seconds. */ 237 char name[RTE_NODE_NAMESIZE]; /**< Name of the node. */ 238 } __rte_cache_aligned; 239 240 /** 241 * Create Graph. 242 * 243 * Create memory reel, detect loops and find isolated nodes. 244 * 245 * @param name 246 * Unique name for this graph. 247 * @param prm 248 * Graph parameter, includes node names and count to be included 249 * in this graph. 250 * 251 * @return 252 * Unique graph id on success, RTE_GRAPH_ID_INVALID otherwise. 253 */ 254 __rte_experimental 255 rte_graph_t rte_graph_create(const char *name, struct rte_graph_param *prm); 256 257 /** 258 * Destroy Graph. 259 * 260 * Free Graph memory reel. 261 * 262 * @param id 263 * id of the graph to destroy. 264 * 265 * @return 266 * 0 on success, error otherwise. 267 */ 268 __rte_experimental 269 int rte_graph_destroy(rte_graph_t id); 270 271 /** 272 * Clone Graph. 273 * 274 * Clone a graph from static graph (graph created from rte_graph_create()). And 275 * all cloned graphs attached to the parent graph MUST be destroyed together 276 * for fast schedule design limitation (stop ALL graph walk firstly). 277 * 278 * @param id 279 * Static graph id to clone from. 280 * @param name 281 * Name of the new graph. The library prepends the parent graph name to the 282 * user-specified name. The final graph name will be, 283 * "parent graph name" + "-" + name. 284 * @param prm 285 * Graph parameter, includes model-specific parameters in this graph. 286 * 287 * @return 288 * Valid graph id on success, RTE_GRAPH_ID_INVALID otherwise. 289 */ 290 __rte_experimental 291 rte_graph_t rte_graph_clone(rte_graph_t id, const char *name, struct rte_graph_param *prm); 292 293 /** 294 * Get graph id from graph name. 295 * 296 * @param name 297 * Name of the graph to get id. 298 * 299 * @return 300 * Graph id on success, RTE_GRAPH_ID_INVALID otherwise. 301 */ 302 __rte_experimental 303 rte_graph_t rte_graph_from_name(const char *name); 304 305 /** 306 * Get graph name from graph id. 307 * 308 * @param id 309 * id of the graph to get name. 310 * 311 * @return 312 * Graph name on success, NULL otherwise. 313 */ 314 __rte_experimental 315 char *rte_graph_id_to_name(rte_graph_t id); 316 317 /** 318 * Export the graph as graph viz dot file 319 * 320 * @param name 321 * Name of the graph to export. 322 * @param f 323 * File pointer to export the graph. 324 * 325 * @return 326 * 0 on success, error otherwise. 327 */ 328 __rte_experimental 329 int rte_graph_export(const char *name, FILE *f); 330 331 /** 332 * Bind graph with specific lcore for mcore dispatch model. 333 * 334 * @param id 335 * Graph id to get the pointer of graph object 336 * @param lcore 337 * The lcore where the graph will run on 338 * @return 339 * 0 on success, error otherwise. 340 */ 341 __rte_experimental 342 int rte_graph_model_mcore_dispatch_core_bind(rte_graph_t id, int lcore); 343 344 /** 345 * Unbind graph with lcore for mcore dispatch model 346 * 347 * @param id 348 * Graph id to get the pointer of graph object 349 */ 350 __rte_experimental 351 void rte_graph_model_mcore_dispatch_core_unbind(rte_graph_t id); 352 353 /** 354 * Get graph object from its name. 355 * 356 * Typical usage of this API to get graph objects in the worker thread and 357 * followed calling rte_graph_walk() in a loop. 358 * 359 * @param name 360 * Name of the graph. 361 * 362 * @return 363 * Graph pointer on success, NULL otherwise. 364 * 365 * @see rte_graph_walk() 366 */ 367 __rte_experimental 368 struct rte_graph *rte_graph_lookup(const char *name); 369 370 /** 371 * Get maximum number of graph available. 372 * 373 * @return 374 * Maximum graph count. 375 */ 376 __rte_experimental 377 rte_graph_t rte_graph_max_count(void); 378 379 /** 380 * Dump the graph information to file. 381 * 382 * @param f 383 * File pointer to dump graph info. 384 * @param id 385 * Graph id to get graph info. 386 */ 387 __rte_experimental 388 void rte_graph_dump(FILE *f, rte_graph_t id); 389 390 /** 391 * Dump all graphs information to file 392 * 393 * @param f 394 * File pointer to dump graph info. 395 */ 396 __rte_experimental 397 void rte_graph_list_dump(FILE *f); 398 399 /** 400 * Dump graph information along with node info to file 401 * 402 * @param f 403 * File pointer to dump graph info. 404 * @param graph 405 * Graph pointer to get graph info. 406 * @param all 407 * true to dump nodes in the graph. 408 */ 409 __rte_experimental 410 void rte_graph_obj_dump(FILE *f, struct rte_graph *graph, bool all); 411 412 /** Macro to browse rte_node object after the graph creation */ 413 #define rte_graph_foreach_node(count, off, graph, node) \ 414 for (count = 0, off = graph->nodes_start, \ 415 node = RTE_PTR_ADD(graph, off); \ 416 count < graph->nb_nodes; \ 417 off = node->next, node = RTE_PTR_ADD(graph, off), count++) 418 419 /** 420 * Get node object with in graph from id. 421 * 422 * @param graph_id 423 * Graph id to get node pointer from. 424 * @param node_id 425 * Node id to get node pointer. 426 * 427 * @return 428 * Node pointer on success, NULL otherwise. 429 */ 430 __rte_experimental 431 struct rte_node *rte_graph_node_get(rte_graph_t graph_id, rte_node_t node_id); 432 433 /** 434 * Get node pointer with in graph from name. 435 * 436 * @param graph 437 * Graph name to get node pointer from. 438 * @param name 439 * Node name to get the node pointer. 440 * 441 * @return 442 * Node pointer on success, NULL otherwise. 443 */ 444 __rte_experimental 445 struct rte_node *rte_graph_node_get_by_name(const char *graph, 446 const char *name); 447 448 /** 449 * Create graph stats cluster to aggregate runtime node stats. 450 * 451 * @param prm 452 * Parameters including file pointer to dump stats, 453 * Graph pattern to create cluster and callback function. 454 * 455 * @return 456 * Valid pointer on success, NULL otherwise. 457 */ 458 __rte_experimental 459 struct rte_graph_cluster_stats *rte_graph_cluster_stats_create( 460 const struct rte_graph_cluster_stats_param *prm); 461 462 /** 463 * Destroy cluster stats. 464 * 465 * @param stat 466 * Valid cluster pointer to destroy. 467 */ 468 __rte_experimental 469 void rte_graph_cluster_stats_destroy(struct rte_graph_cluster_stats *stat); 470 471 /** 472 * Get stats to application. 473 * 474 * @param[out] stat 475 * Cluster status. 476 * @param skip_cb 477 * true to skip callback function invocation. 478 */ 479 __rte_experimental 480 void rte_graph_cluster_stats_get(struct rte_graph_cluster_stats *stat, 481 bool skip_cb); 482 483 /** 484 * Reset cluster stats to zero. 485 * 486 * @param stat 487 * Valid cluster stats pointer. 488 */ 489 __rte_experimental 490 void rte_graph_cluster_stats_reset(struct rte_graph_cluster_stats *stat); 491 492 /** 493 * Structure defines the node registration parameters. 494 * 495 * @see __rte_node_register(), RTE_NODE_REGISTER() 496 */ 497 struct rte_node_register { 498 char name[RTE_NODE_NAMESIZE]; /**< Name of the node. */ 499 uint64_t flags; /**< Node configuration flag. */ 500 #define RTE_NODE_SOURCE_F (1ULL << 0) /**< Node type is source. */ 501 rte_node_process_t process; /**< Node process function. */ 502 rte_node_init_t init; /**< Node init function. */ 503 rte_node_fini_t fini; /**< Node fini function. */ 504 rte_node_t id; /**< Node Identifier. */ 505 rte_node_t parent_id; /**< Identifier of parent node. */ 506 rte_edge_t nb_edges; /**< Number of edges from this node. */ 507 const char *next_nodes[]; /**< Names of next nodes. */ 508 }; 509 510 /** 511 * Register new packet processing node. Nodes can be registered 512 * dynamically via this call or statically via the RTE_NODE_REGISTER 513 * macro. 514 * 515 * @param node 516 * Valid node pointer with name, process function and next_nodes. 517 * 518 * @return 519 * Valid node id on success, RTE_NODE_ID_INVALID otherwise. 520 * 521 * @see RTE_NODE_REGISTER() 522 */ 523 __rte_experimental 524 rte_node_t __rte_node_register(const struct rte_node_register *node); 525 526 /** 527 * Register a static node. 528 * 529 * The static node is registered through the constructor scheme, thereby, it can 530 * be used in a multi-process scenario. 531 * 532 * @param node 533 * Valid node pointer with name, process function, and next_nodes. 534 */ 535 #define RTE_NODE_REGISTER(node) \ 536 RTE_INIT(rte_node_register_##node) \ 537 { \ 538 node.parent_id = RTE_NODE_ID_INVALID; \ 539 node.id = __rte_node_register(&node); \ 540 } 541 542 /** 543 * Clone a node from static node(node created from RTE_NODE_REGISTER). 544 * 545 * @param id 546 * Static node id to clone from. 547 * @param name 548 * Name of the new node. The library prepends the parent node name to the 549 * user-specified name. The final node name will be, 550 * "parent node name" + "-" + name. 551 * 552 * @return 553 * Valid node id on success, RTE_NODE_ID_INVALID otherwise. 554 */ 555 __rte_experimental 556 rte_node_t rte_node_clone(rte_node_t id, const char *name); 557 558 /** 559 * Get node id from node name. 560 * 561 * @param name 562 * Valid node name. In the case of the cloned node, the name will be 563 * "parent node name" + "-" + name. 564 * 565 * @return 566 * Valid node id on success, RTE_NODE_ID_INVALID otherwise. 567 */ 568 __rte_experimental 569 rte_node_t rte_node_from_name(const char *name); 570 571 /** 572 * Get node name from node id. 573 * 574 * @param id 575 * Valid node id. 576 * 577 * @return 578 * Valid node name on success, NULL otherwise. 579 */ 580 __rte_experimental 581 char *rte_node_id_to_name(rte_node_t id); 582 583 /** 584 * Get the number of edges(next-nodes) for a node from node id. 585 * 586 * @param id 587 * Valid node id. 588 * 589 * @return 590 * Valid edge count on success, RTE_EDGE_ID_INVALID otherwise. 591 */ 592 __rte_experimental 593 rte_edge_t rte_node_edge_count(rte_node_t id); 594 595 /** 596 * Update the edges for a node from node id. 597 * 598 * @param id 599 * Valid node id. 600 * @param from 601 * Index to update the edges from. RTE_EDGE_ID_INVALID is valid, 602 * in that case, it will be added to the end of the list. 603 * @param next_nodes 604 * Name of the edges to update. 605 * @param nb_edges 606 * Number of edges to update. 607 * 608 * @return 609 * Valid edge count on success, 0 otherwise. 610 */ 611 __rte_experimental 612 rte_edge_t rte_node_edge_update(rte_node_t id, rte_edge_t from, 613 const char **next_nodes, uint16_t nb_edges); 614 615 /** 616 * Shrink the edges to a given size. 617 * 618 * @param id 619 * Valid node id. 620 * @param size 621 * New size to shrink the edges. 622 * 623 * @return 624 * New size on success, RTE_EDGE_ID_INVALID otherwise. 625 */ 626 __rte_experimental 627 rte_edge_t rte_node_edge_shrink(rte_node_t id, rte_edge_t size); 628 629 /** 630 * Get the edge names from a given node. 631 * 632 * @param id 633 * Valid node id. 634 * @param[out] next_nodes 635 * Buffer to copy the edge names. The NULL value is allowed in that case, 636 * the function returns the size of the array that needs to be allocated. 637 * 638 * @return 639 * When next_nodes == NULL, it returns the size of the array else 640 * number of item copied. 641 */ 642 __rte_experimental 643 rte_node_t rte_node_edge_get(rte_node_t id, char *next_nodes[]); 644 645 /** 646 * Get maximum nodes available. 647 * 648 * @return 649 * Maximum nodes count. 650 */ 651 __rte_experimental 652 rte_node_t rte_node_max_count(void); 653 654 /** 655 * Dump node info to file. 656 * 657 * @param f 658 * File pointer to dump the node info. 659 * @param id 660 * Node id to get the info. 661 */ 662 __rte_experimental 663 void rte_node_dump(FILE *f, rte_node_t id); 664 665 /** 666 * Dump all node info to file. 667 * 668 * @param f 669 * File pointer to dump the node info. 670 */ 671 __rte_experimental 672 void rte_node_list_dump(FILE *f); 673 674 /** 675 * Test the validity of node id. 676 * 677 * @param id 678 * Node id to check. 679 * 680 * @return 681 * 1 if valid id, 0 otherwise. 682 */ 683 static __rte_always_inline int 684 rte_node_is_invalid(rte_node_t id) 685 { 686 return (id == RTE_NODE_ID_INVALID); 687 } 688 689 /** 690 * Test the validity of edge id. 691 * 692 * @param id 693 * Edge node id to check. 694 * 695 * @return 696 * 1 if valid id, 0 otherwise. 697 */ 698 static __rte_always_inline int 699 rte_edge_is_invalid(rte_edge_t id) 700 { 701 return (id == RTE_EDGE_ID_INVALID); 702 } 703 704 /** 705 * Test the validity of graph id. 706 * 707 * @param id 708 * Graph id to check. 709 * 710 * @return 711 * 1 if valid id, 0 otherwise. 712 */ 713 static __rte_always_inline int 714 rte_graph_is_invalid(rte_graph_t id) 715 { 716 return (id == RTE_GRAPH_ID_INVALID); 717 } 718 719 /** 720 * Test stats feature support. 721 * 722 * @return 723 * 1 if stats enabled, 0 otherwise. 724 */ 725 static __rte_always_inline int 726 rte_graph_has_stats_feature(void) 727 { 728 #ifdef RTE_LIBRTE_GRAPH_STATS 729 return RTE_LIBRTE_GRAPH_STATS; 730 #else 731 return 0; 732 #endif 733 } 734 735 #ifdef __cplusplus 736 } 737 #endif 738 739 #endif /* _RTE_GRAPH_H_ */ 740