1 /*
2  * libqos driver framework
3  *
4  * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License version 2.1 as published by the Free Software Foundation.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, see <http://www.gnu.org/licenses/>
17  */
18 
19 #ifndef QGRAPH_INTERNAL_H
20 #define QGRAPH_INTERNAL_H
21 
22 /* This header is declaring additional helper functions defined in
23  * qgraph.c
24  * It should not be included in tests
25  */
26 
27 #include "qgraph.h"
28 
29 typedef struct QOSGraphMachine QOSGraphMachine;
30 typedef enum QOSEdgeType QOSEdgeType;
31 typedef enum QOSNodeType QOSNodeType;
32 
33 /* callback called when the walk path algorithm found a
34  * valid path
35  */
36 typedef void (*QOSTestCallback) (QOSGraphNode *path, int len);
37 
38 /* edge types*/
39 enum QOSEdgeType {
40     QEDGE_CONTAINS,
41     QEDGE_PRODUCES,
42     QEDGE_CONSUMED_BY
43 };
44 
45 /* node types*/
46 enum QOSNodeType {
47     QNODE_MACHINE,
48     QNODE_DRIVER,
49     QNODE_INTERFACE,
50     QNODE_TEST
51 };
52 
53 /* Graph Node */
54 struct QOSGraphNode {
55     QOSNodeType type;
56     bool available;     /* set by QEMU via QMP, used during graph walk */
57     bool visited;       /* used during graph walk */
58     char *name;         /* used to identify the node */
59     char *qemu_name;    /* optional: see qos_node_create_driver_named() */
60     char *command_line; /* used to start QEMU at test execution */
61     union {
62         struct {
63             QOSCreateDriverFunc constructor;
64         } driver;
65         struct {
66             QOSCreateMachineFunc constructor;
67         } machine;
68         struct {
69             QOSTestFunc function;
70             void *arg;
71             QOSBeforeTest before;
72             bool subprocess;
73         } test;
74     } u;
75 
76     /**
77      * only used when traversing the path, never rely on that except in the
78      * qos_traverse_graph callback function
79      */
80     QOSGraphEdge *path_edge;
81 };
82 
83 /**
84  * qos_graph_get_node(): returns the node mapped to that @key.
85  * It performs an hash map search O(1)
86  *
87  * Returns: on success: the %QOSGraphNode
88  *          otherwise: #NULL
89  */
90 QOSGraphNode *qos_graph_get_node(const char *key);
91 
92 /**
93  * qos_graph_has_node(): returns #TRUE if the node
94  * has map has a node mapped to that @key.
95  */
96 bool qos_graph_has_node(const char *node);
97 
98 /**
99  * qos_graph_get_node_type(): returns the %QOSNodeType
100  * of the node @node.
101  * It performs an hash map search O(1)
102  * Returns: on success: the %QOSNodeType
103  *          otherwise: #-1
104  */
105 QOSNodeType qos_graph_get_node_type(const char *node);
106 
107 /**
108  * qos_graph_get_node_availability(): returns the availability (boolean)
109  * of the node @node.
110  */
111 bool qos_graph_get_node_availability(const char *node);
112 
113 /**
114  * qos_graph_get_edge(): returns the edge
115  * linking of the node @node with @dest.
116  *
117  * Returns: on success: the %QOSGraphEdge
118  *          otherwise: #NULL
119  */
120 QOSGraphEdge *qos_graph_get_edge(const char *node, const char *dest);
121 
122 /**
123  * qos_graph_edge_get_type(): returns the edge type
124  * of the edge @edge.
125  *
126  * Returns: on success: the %QOSEdgeType
127  *          otherwise: #-1
128  */
129 QOSEdgeType qos_graph_edge_get_type(QOSGraphEdge *edge);
130 
131 /**
132  * qos_graph_edge_get_dest(): returns the name of the node
133  * pointed as destination of edge @edge.
134  *
135  * Returns: on success: the destination
136  *          otherwise: #NULL
137  */
138 char *qos_graph_edge_get_dest(QOSGraphEdge *edge);
139 
140 /**
141  * qos_graph_has_edge(): returns #TRUE if there
142  * exists an edge from @start to @dest.
143  */
144 bool qos_graph_has_edge(const char *start, const char *dest);
145 
146 /**
147  * qos_graph_edge_get_arg(): returns the args assigned
148  * to that @edge.
149  *
150  * Returns: on success: the arg
151  *          otherwise: #NULL
152  */
153 void *qos_graph_edge_get_arg(QOSGraphEdge *edge);
154 
155 /**
156  * qos_graph_edge_get_after_cmd_line(): returns the edge
157  * command line that will be added after all the node arguments
158  * and all the before_cmd_line arguments.
159  *
160  * Returns: on success: the char* arg
161  *          otherwise: #NULL
162  */
163 char *qos_graph_edge_get_after_cmd_line(QOSGraphEdge *edge);
164 
165 /**
166  * qos_graph_edge_get_before_cmd_line(): returns the edge
167  * command line that will be added before the node command
168  * line argument.
169  *
170  * Returns: on success: the char* arg
171  *          otherwise: #NULL
172  */
173 char *qos_graph_edge_get_before_cmd_line(QOSGraphEdge *edge);
174 
175 /**
176  * qos_graph_edge_get_extra_device_opts(): returns the arg
177  * command line that will be added to the node command
178  * line argument.
179  *
180  * Returns: on success: the char* arg
181  *          otherwise: #NULL
182  */
183 char *qos_graph_edge_get_extra_device_opts(QOSGraphEdge *edge);
184 
185 /**
186  * qos_graph_edge_get_name(): returns the name
187  * assigned to the destination node (different only)
188  * if there are multiple devices with the same node name
189  * e.g. a node has two "generic-sdhci", "emmc" and "sdcard"
190  * there will be two edges with edge_name ="emmc" and "sdcard"
191  *
192  * Returns always the char* edge_name
193  */
194 char *qos_graph_edge_get_name(QOSGraphEdge *edge);
195 
196 /**
197  * qos_graph_get_machine(): returns the machine assigned
198  * to that @node name.
199  *
200  * It performs a search only trough the list of machines
201  * (i.e. the QOS_ROOT child).
202  *
203  * Returns: on success: the %QOSGraphNode
204  *          otherwise: #NULL
205  */
206 QOSGraphNode *qos_graph_get_machine(const char *node);
207 
208 /**
209  * qos_graph_has_machine(): returns #TRUE if the node
210  * has map has a node mapped to that @node.
211  */
212 bool qos_graph_has_machine(const char *node);
213 
214 
215 /**
216  * qos_print_graph(): walks the graph and prints
217  * all machine-to-test paths.
218  */
219 void qos_print_graph(void);
220 
221 /**
222  * qos_graph_foreach_test_path(): executes the Depth First search
223  * algorithm and applies @fn to all discovered paths.
224  *
225  * See qos_traverse_graph() in qgraph.c for more info on
226  * how it works.
227  */
228 void qos_graph_foreach_test_path(QOSTestCallback fn);
229 
230 /**
231  * qos_get_machine_type(): return QEMU machine type for a machine node.
232  * This function requires every machine @name to be in the form
233  * <arch>/<machine_name>, like "arm/raspi2b" or "x86_64/pc".
234  *
235  * The function will validate the format and return a pointer to
236  * @machine to <machine_name>.  For example, when passed "x86_64/pc"
237  * it will return "pc".
238  *
239  * Note that this function *does not* allocate any new string.
240  */
241 char *qos_get_machine_type(char *name);
242 
243 /**
244  * qos_delete_cmd_line(): delete the
245  * command line present in node mapped with key @name.
246  *
247  * This function is called when the QMP query returns a node with
248  * { "abstract" : true } attribute.
249  */
250 void qos_delete_cmd_line(const char *name);
251 
252 /**
253  * qos_graph_node_set_availability(): sets the node identified
254  * by @node with availability @av.
255  */
256 void qos_graph_node_set_availability(const char *node, bool av);
257 
258 /*
259  * Prepends a '#' character in front for not breaking TAP output format.
260  */
261 #define qos_printf(...) printf("# " __VA_ARGS__)
262 
263 /*
264  * Intended for printing something literally, i.e. for appending text as is
265  * to a line already been started by qos_printf() before.
266  */
267 #define qos_printf_literal printf
268 
269 #endif
270