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