xref: /dpdk/lib/graph/rte_graph.h (revision a8ca598cd8e696b4135f04cdd86a93b12fd5642a)
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