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