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
rte_node_is_invalid(rte_node_t id)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
rte_edge_is_invalid(rte_edge_t id)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
rte_graph_is_invalid(rte_graph_t id)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
rte_graph_has_stats_feature(void)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