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