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