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