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 *command_line; /* used to start QEMU at test execution */
60     union {
61         struct {
62             QOSCreateDriverFunc constructor;
63         } driver;
64         struct {
65             QOSCreateMachineFunc constructor;
66         } machine;
67         struct {
68             QOSTestFunc function;
69             void *arg;
70             QOSBeforeTest before;
71             bool subprocess;
72         } test;
73     } u;
74 
75     /**
76      * only used when traversing the path, never rely on that except in the
77      * qos_traverse_graph callback function
78      */
79     QOSGraphEdge *path_edge;
80 };
81 
82 /**
83  * qos_graph_get_node(): returns the node mapped to that @key.
84  * It performs an hash map search O(1)
85  *
86  * Returns: on success: the %QOSGraphNode
87  *          otherwise: #NULL
88  */
89 QOSGraphNode *qos_graph_get_node(const char *key);
90 
91 /**
92  * qos_graph_has_node(): returns #TRUE if the node
93  * has map has a node mapped to that @key.
94  */
95 bool qos_graph_has_node(const char *node);
96 
97 /**
98  * qos_graph_get_node_type(): returns the %QOSNodeType
99  * of the node @node.
100  * It performs an hash map search O(1)
101  * Returns: on success: the %QOSNodeType
102  *          otherwise: #-1
103  */
104 QOSNodeType qos_graph_get_node_type(const char *node);
105 
106 /**
107  * qos_graph_get_node_availability(): returns the availability (boolean)
108  * of the node @node.
109  */
110 bool qos_graph_get_node_availability(const char *node);
111 
112 /**
113  * qos_graph_get_edge(): returns the edge
114  * linking of the node @node with @dest.
115  *
116  * Returns: on success: the %QOSGraphEdge
117  *          otherwise: #NULL
118  */
119 QOSGraphEdge *qos_graph_get_edge(const char *node, const char *dest);
120 
121 /**
122  * qos_graph_edge_get_type(): returns the edge type
123  * of the edge @edge.
124  *
125  * Returns: on success: the %QOSEdgeType
126  *          otherwise: #-1
127  */
128 QOSEdgeType qos_graph_edge_get_type(QOSGraphEdge *edge);
129 
130 /**
131  * qos_graph_edge_get_dest(): returns the name of the node
132  * pointed as destination of edge @edge.
133  *
134  * Returns: on success: the destination
135  *          otherwise: #NULL
136  */
137 char *qos_graph_edge_get_dest(QOSGraphEdge *edge);
138 
139 /**
140  * qos_graph_has_edge(): returns #TRUE if there
141  * exists an edge from @start to @dest.
142  */
143 bool qos_graph_has_edge(const char *start, const char *dest);
144 
145 /**
146  * qos_graph_edge_get_arg(): returns the args assigned
147  * to that @edge.
148  *
149  * Returns: on success: the arg
150  *          otherwise: #NULL
151  */
152 void *qos_graph_edge_get_arg(QOSGraphEdge *edge);
153 
154 /**
155  * qos_graph_edge_get_after_cmd_line(): returns the edge
156  * command line that will be added after all the node arguments
157  * and all the before_cmd_line arguments.
158  *
159  * Returns: on success: the char* arg
160  *          otherwise: #NULL
161  */
162 char *qos_graph_edge_get_after_cmd_line(QOSGraphEdge *edge);
163 
164 /**
165  * qos_graph_edge_get_before_cmd_line(): returns the edge
166  * command line that will be added before the node command
167  * line argument.
168  *
169  * Returns: on success: the char* arg
170  *          otherwise: #NULL
171  */
172 char *qos_graph_edge_get_before_cmd_line(QOSGraphEdge *edge);
173 
174 /**
175  * qos_graph_edge_get_extra_device_opts(): returns the arg
176  * command line that will be added to the node command
177  * line argument.
178  *
179  * Returns: on success: the char* arg
180  *          otherwise: #NULL
181  */
182 char *qos_graph_edge_get_extra_device_opts(QOSGraphEdge *edge);
183 
184 /**
185  * qos_graph_edge_get_name(): returns the name
186  * assigned to the destination node (different only)
187  * if there are multiple devices with the same node name
188  * e.g. a node has two "generic-sdhci", "emmc" and "sdcard"
189  * there will be two edges with edge_name ="emmc" and "sdcard"
190  *
191  * Returns always the char* edge_name
192  */
193 char *qos_graph_edge_get_name(QOSGraphEdge *edge);
194 
195 /**
196  * qos_graph_get_machine(): returns the machine assigned
197  * to that @node name.
198  *
199  * It performs a search only trough the list of machines
200  * (i.e. the QOS_ROOT child).
201  *
202  * Returns: on success: the %QOSGraphNode
203  *          otherwise: #NULL
204  */
205 QOSGraphNode *qos_graph_get_machine(const char *node);
206 
207 /**
208  * qos_graph_has_machine(): returns #TRUE if the node
209  * has map has a node mapped to that @node.
210  */
211 bool qos_graph_has_machine(const char *node);
212 
213 
214 /**
215  * qos_print_graph(): walks the graph and prints
216  * all machine-to-test paths.
217  */
218 void qos_print_graph(void);
219 
220 /**
221  * qos_graph_foreach_test_path(): executes the Depth First search
222  * algorithm and applies @fn to all discovered paths.
223  *
224  * See qos_traverse_graph() in qgraph.c for more info on
225  * how it works.
226  */
227 void qos_graph_foreach_test_path(QOSTestCallback fn);
228 
229 /**
230  * qos_get_machine_type(): return QEMU machine type for a machine node.
231  * This function requires every machine @name to be in the form
232  * <arch>/<machine_name>, like "arm/raspi2" or "x86_64/pc".
233  *
234  * The function will validate the format and return a pointer to
235  * @machine to <machine_name>.  For example, when passed "x86_64/pc"
236  * it will return "pc".
237  *
238  * Note that this function *does not* allocate any new string.
239  */
240 char *qos_get_machine_type(char *name);
241 
242 /**
243  * qos_delete_cmd_line(): delete the
244  * command line present in node mapped with key @name.
245  *
246  * This function is called when the QMP query returns a node with
247  * { "abstract" : true } attribute.
248  */
249 void qos_delete_cmd_line(const char *name);
250 
251 /**
252  * qos_graph_node_set_availability(): sets the node identified
253  * by @node with availability @av.
254  */
255 void qos_graph_node_set_availability(const char *node, bool av);
256 
257 #endif
258