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