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