libqos/qgraph: format qgraph comments for sphinx documentation
Change documentation style and fix minor typos in tests/qtest/libqos/qgraph.h to automatically generate sphinx documentation in docs/devel/qgraph.rst The mechanism explanation that once was in qgraph.h is now moved to qgraph.rst There is no functional change intended. Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> Message-Id: <20210308073240.6363-1-eesposit@redhat.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
parent
6179f32eeb
commit
222455ef81
@ -2607,6 +2607,7 @@ S: Maintained
|
|||||||
F: softmmu/qtest.c
|
F: softmmu/qtest.c
|
||||||
F: accel/qtest/
|
F: accel/qtest/
|
||||||
F: tests/qtest/
|
F: tests/qtest/
|
||||||
|
F: docs/devel/qgraph.rst
|
||||||
X: tests/qtest/bios-tables-test*
|
X: tests/qtest/bios-tables-test*
|
||||||
|
|
||||||
Device Fuzzing
|
Device Fuzzing
|
||||||
|
@ -12,6 +12,7 @@ Contents:
|
|||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
:includehidden:
|
||||||
|
|
||||||
build-system
|
build-system
|
||||||
style
|
style
|
||||||
|
261
docs/devel/qgraph.rst
Normal file
261
docs/devel/qgraph.rst
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
.. _qgraph:
|
||||||
|
|
||||||
|
========================================
|
||||||
|
Qtest Driver Framework
|
||||||
|
========================================
|
||||||
|
|
||||||
|
This Qgraph API provides all basic functions to create a graph
|
||||||
|
and instantiate nodes representing machines, drivers and tests
|
||||||
|
representing their relations with ``CONSUMES``, ``PRODUCES``, and
|
||||||
|
``CONTAINS`` edges.
|
||||||
|
|
||||||
|
The idea is to have a framework where each test asks for a specific
|
||||||
|
driver, and the framework takes care of allocating the proper devices
|
||||||
|
required and passing the correct command line arguments to QEMU.
|
||||||
|
|
||||||
|
Nodes
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
A node can be of four types:
|
||||||
|
|
||||||
|
- **QNODE_MACHINE**: for example ``arm/raspi2``
|
||||||
|
- **QNODE_DRIVER**: for example ``generic-sdhci``
|
||||||
|
- **QNODE_INTERFACE**: for example ``sdhci`` (interface for all ``-sdhci``
|
||||||
|
drivers).
|
||||||
|
An interface is not explicitly created, it will be automatically
|
||||||
|
instantiated when a node consumes or produces it.
|
||||||
|
- **QNODE_TEST**: for example ``sdhci-test``, consumes an interface and
|
||||||
|
tests the functions provided.
|
||||||
|
|
||||||
|
Notes for the nodes:
|
||||||
|
|
||||||
|
- QNODE_MACHINE: each machine struct must have a ``QGuestAllocator`` and
|
||||||
|
implement ``get_driver()`` to return the allocator mapped to the interface
|
||||||
|
"memory". The function can also return ``NULL`` if the allocator
|
||||||
|
is not set.
|
||||||
|
- QNODE_DRIVER: driver names must be unique, and machines and nodes
|
||||||
|
planned to be "consumed" by other nodes must match QEMU
|
||||||
|
drivers name, otherwise they won't be discovered
|
||||||
|
|
||||||
|
Edges
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
An edge relation between two nodes (drivers or machines) `X` and `Y` can be:
|
||||||
|
|
||||||
|
- ``X CONSUMES Y``: `Y` can be plugged into `X`
|
||||||
|
- ``X PRODUCES Y``: `X` provides the interface `Y`
|
||||||
|
- ``X CONTAINS Y``: `Y` is part of `X` component
|
||||||
|
|
||||||
|
Execution steps
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The basic framework steps are the following:
|
||||||
|
|
||||||
|
- All nodes and edges are created in their respective
|
||||||
|
machine/driver/test files
|
||||||
|
- The framework starts QEMU and asks for a list of available devices
|
||||||
|
and machines (note that only machines and "consumed" nodes are mapped
|
||||||
|
1:1 with QEMU devices)
|
||||||
|
- The framework walks the graph starting from the available machines and
|
||||||
|
performs a Depth First Search for tests
|
||||||
|
- Once a test is found, the path is walked again and all drivers are
|
||||||
|
allocated accordingly and the final interface is passed to the test
|
||||||
|
- The test is executed
|
||||||
|
- Unused objects are cleaned and the path discovery is continued
|
||||||
|
|
||||||
|
Depending on the QEMU binary used, only some drivers/machines will be
|
||||||
|
available and only test that are reached by them will be executed.
|
||||||
|
|
||||||
|
Creating a new driver and its interface
|
||||||
|
"""""""""""""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
#include "qgraph.h"
|
||||||
|
|
||||||
|
struct My_driver {
|
||||||
|
QOSGraphObject obj;
|
||||||
|
Node_produced prod;
|
||||||
|
Node_contained cont;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_destructor(QOSGraphObject *obj)
|
||||||
|
{
|
||||||
|
g_free(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *my_get_driver(void *object, const char *interface) {
|
||||||
|
My_driver *dev = object;
|
||||||
|
if (!g_strcmp0(interface, "my_interface")) {
|
||||||
|
return &dev->prod;
|
||||||
|
}
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *my_get_device(void *object, const char *device) {
|
||||||
|
My_driver *dev = object;
|
||||||
|
if (!g_strcmp0(device, "my_driver_contained")) {
|
||||||
|
return &dev->cont;
|
||||||
|
}
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *my_driver_constructor(void *node_consumed,
|
||||||
|
QOSGraphObject *alloc)
|
||||||
|
{
|
||||||
|
My_driver dev = g_new(My_driver, 1);
|
||||||
|
|
||||||
|
// get the node pointed by the produce edge
|
||||||
|
dev->obj.get_driver = my_get_driver;
|
||||||
|
|
||||||
|
// get the node pointed by the contains
|
||||||
|
dev->obj.get_device = my_get_device;
|
||||||
|
|
||||||
|
// free the object
|
||||||
|
dev->obj.destructor = my_destructor;
|
||||||
|
|
||||||
|
do_something_with_node_consumed(node_consumed);
|
||||||
|
|
||||||
|
// set all fields of contained device
|
||||||
|
init_contained_device(&dev->cont);
|
||||||
|
return &dev->obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void register_my_driver(void)
|
||||||
|
{
|
||||||
|
qos_node_create_driver("my_driver", my_driver_constructor);
|
||||||
|
|
||||||
|
// contained drivers don't need a constructor,
|
||||||
|
// they will be init by the parent.
|
||||||
|
qos_node_create_driver("my_driver_contained", NULL);
|
||||||
|
|
||||||
|
// For the sake of this example, assume machine x86_64/pc
|
||||||
|
// contains "other_node".
|
||||||
|
// This relation, along with the machine and "other_node"
|
||||||
|
// creation, should be defined in the x86_64_pc-machine.c file.
|
||||||
|
// "my_driver" will then consume "other_node"
|
||||||
|
qos_node_contains("my_driver", "my_driver_contained");
|
||||||
|
qos_node_produces("my_driver", "my_interface");
|
||||||
|
qos_node_consumes("my_driver", "other_node");
|
||||||
|
}
|
||||||
|
|
||||||
|
In the above example, all possible types of relations are created:
|
||||||
|
node "my_driver" consumes, contains and produces other nodes.
|
||||||
|
More specifically::
|
||||||
|
|
||||||
|
x86_64/pc -->contains--> other_node <--consumes-- my_driver
|
||||||
|
|
|
||||||
|
my_driver_contained <--contains--+
|
||||||
|
|
|
||||||
|
my_interface <--produces--+
|
||||||
|
|
||||||
|
or inverting the consumes edge in consumed_by::
|
||||||
|
|
||||||
|
x86_64/pc -->contains--> other_node --consumed_by--> my_driver
|
||||||
|
|
|
||||||
|
my_driver_contained <--contains--+
|
||||||
|
|
|
||||||
|
my_interface <--produces--+
|
||||||
|
|
||||||
|
Creating new test
|
||||||
|
"""""""""""""""""
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
#include "qgraph.h"
|
||||||
|
|
||||||
|
static void my_test_function(void *obj, void *data)
|
||||||
|
{
|
||||||
|
Node_produced *interface_to_test = obj;
|
||||||
|
// test interface_to_test
|
||||||
|
}
|
||||||
|
|
||||||
|
static void register_my_test(void)
|
||||||
|
{
|
||||||
|
qos_add_test("my_interface", "my_test", my_test_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
libqos_init(register_my_test);
|
||||||
|
|
||||||
|
Here a new test is created, consuming "my_interface" node
|
||||||
|
and creating a valid path from a machine to a test.
|
||||||
|
Final graph will be like this::
|
||||||
|
|
||||||
|
x86_64/pc --contains--> other_node <--consumes-- my_driver
|
||||||
|
|
|
||||||
|
my_driver_contained <--contains--+
|
||||||
|
|
|
||||||
|
my_test --consumes--> my_interface <--produces--+
|
||||||
|
|
||||||
|
or inverting the consumes edge in consumed_by::
|
||||||
|
|
||||||
|
x86_64/pc --contains--> other_node --consumed_by--> my_driver
|
||||||
|
|
|
||||||
|
my_driver_contained <--contains--+
|
||||||
|
|
|
||||||
|
my_test <--consumed_by-- my_interface <--produces--+
|
||||||
|
|
||||||
|
Assuming there the binary is
|
||||||
|
``QTEST_QEMU_BINARY=./qemu-system-x86_64``
|
||||||
|
a valid test path will be:
|
||||||
|
``/x86_64/pc/other_node/my_driver/my_interface/my_test``.
|
||||||
|
|
||||||
|
Additional examples are also in ``test-qgraph.c``
|
||||||
|
|
||||||
|
Command line:
|
||||||
|
""""""""""""""
|
||||||
|
|
||||||
|
Command line is built by using node names and optional arguments
|
||||||
|
passed by the user when building the edges.
|
||||||
|
|
||||||
|
There are three types of command line arguments:
|
||||||
|
|
||||||
|
- ``in node`` : created from the node name. For example, machines will
|
||||||
|
have ``-M <machine>`` to its command line, while devices
|
||||||
|
``-device <device>``. It is automatically done by the framework.
|
||||||
|
- ``after node`` : added as additional argument to the node name.
|
||||||
|
This argument is added optionally when creating edges,
|
||||||
|
by setting the parameter @after_cmd_line and
|
||||||
|
@extra_edge_opts in #QOSGraphEdgeOptions.
|
||||||
|
The framework automatically adds
|
||||||
|
a comma before @extra_edge_opts,
|
||||||
|
because it is going to add attributes
|
||||||
|
after the destination node pointed by
|
||||||
|
the edge containing these options, and automatically
|
||||||
|
adds a space before @after_cmd_line, because it
|
||||||
|
adds an additional device, not an attribute.
|
||||||
|
- ``before node`` : added as additional argument to the node name.
|
||||||
|
This argument is added optionally when creating edges,
|
||||||
|
by setting the parameter @before_cmd_line in
|
||||||
|
#QOSGraphEdgeOptions. This attribute
|
||||||
|
is going to add attributes before the destination node
|
||||||
|
pointed by the edge containing these options. It is
|
||||||
|
helpful to commands that are not node-representable,
|
||||||
|
such as ``-fdsev`` or ``-netdev``.
|
||||||
|
|
||||||
|
While adding command line in edges is always used, not all nodes names are
|
||||||
|
used in every path walk: this is because the contained or produced ones
|
||||||
|
are already added by QEMU, so only nodes that "consumes" will be used to
|
||||||
|
build the command line. Also, nodes that will have ``{ "abstract" : true }``
|
||||||
|
as QMP attribute will loose their command line, since they are not proper
|
||||||
|
devices to be added in QEMU.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
QOSGraphEdgeOptions opts = {
|
||||||
|
.arg = NULL,
|
||||||
|
.size_arg = 0,
|
||||||
|
.after_cmd_line = "-device other",
|
||||||
|
.before_cmd_line = "-netdev something",
|
||||||
|
.extra_edge_opts = "addr=04.0",
|
||||||
|
};
|
||||||
|
QOSGraphNodeS *node = qos_node_create_driver("my_node", constructor);
|
||||||
|
qos_node_consumes_args("my_node", "interface", &opts);
|
||||||
|
|
||||||
|
Will produce the following command line:
|
||||||
|
``-netdev something -device my_node,addr=04.0 -device other``
|
||||||
|
|
||||||
|
Qgraph API reference
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. kernel-doc:: tests/qtest/libqos/qgraph.h
|
@ -2,6 +2,11 @@
|
|||||||
QTest Device Emulation Testing Framework
|
QTest Device Emulation Testing Framework
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
qgraph
|
||||||
|
|
||||||
QTest is a device emulation testing framework. It can be very useful to test
|
QTest is a device emulation testing framework. It can be very useful to test
|
||||||
device models; it could also control certain aspects of QEMU (such as virtual
|
device models; it could also control certain aspects of QEMU (such as virtual
|
||||||
clock stepping), with a special purpose "qtest" protocol. Refer to
|
clock stepping), with a special purpose "qtest" protocol. Refer to
|
||||||
@ -24,6 +29,9 @@ On top of libqtest, a higher level library, ``libqos``, was created to
|
|||||||
encapsulate common tasks of device drivers, such as memory management and
|
encapsulate common tasks of device drivers, such as memory management and
|
||||||
communicating with system buses or devices. Many virtual device tests use
|
communicating with system buses or devices. Many virtual device tests use
|
||||||
libqos instead of directly calling into libqtest.
|
libqos instead of directly calling into libqtest.
|
||||||
|
Libqos also offers the Qgraph API to increase each test coverage and
|
||||||
|
automate QEMU command line arguments and devices setup.
|
||||||
|
Refer to :ref:`qgraph` for Qgraph explanation and API.
|
||||||
|
|
||||||
Steps to add a new QTest case are:
|
Steps to add a new QTest case are:
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
typedef struct QOSGraphObject QOSGraphObject;
|
typedef struct QOSGraphObject QOSGraphObject;
|
||||||
typedef struct QOSGraphNode QOSGraphNode;
|
typedef struct QOSGraphNode QOSGraphNode;
|
||||||
typedef struct QOSGraphEdge QOSGraphEdge;
|
typedef struct QOSGraphEdge QOSGraphEdge;
|
||||||
typedef struct QOSGraphNodeOptions QOSGraphNodeOptions;
|
|
||||||
typedef struct QOSGraphEdgeOptions QOSGraphEdgeOptions;
|
typedef struct QOSGraphEdgeOptions QOSGraphEdgeOptions;
|
||||||
typedef struct QOSGraphTestOptions QOSGraphTestOptions;
|
typedef struct QOSGraphTestOptions QOSGraphTestOptions;
|
||||||
|
|
||||||
@ -49,340 +48,94 @@ typedef void (*QOSStartFunct) (QOSGraphObject *object);
|
|||||||
typedef void *(*QOSBeforeTest) (GString *cmd_line, void *arg);
|
typedef void *(*QOSBeforeTest) (GString *cmd_line, void *arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION: qgraph.h
|
* struct QOSGraphEdgeOptions:
|
||||||
* @title: Qtest Driver Framework
|
* Edge options to be passed to the contains/consumes \*_args function.
|
||||||
* @short_description: interfaces to organize drivers and tests
|
* @arg: optional arg that will be used by dest edge
|
||||||
* as nodes in a graph
|
* @size_arg: @arg size that will be used by dest edge
|
||||||
*
|
* @extra_device_opts: optional additional command line for dest
|
||||||
* This Qgraph API provides all basic functions to create a graph
|
* edge, used to add additional attributes
|
||||||
* and instantiate nodes representing machines, drivers and tests
|
* *after* the node command line, the
|
||||||
* representing their relations with CONSUMES, PRODUCES, and CONTAINS
|
* framework automatically prepends ","
|
||||||
* edges.
|
* to this argument.
|
||||||
*
|
* @before_cmd_line: optional additional command line for dest
|
||||||
* The idea is to have a framework where each test asks for a specific
|
* edge, used to add additional attributes
|
||||||
* driver, and the framework takes care of allocating the proper devices
|
* *before* the node command line, usually
|
||||||
* required and passing the correct command line arguments to QEMU.
|
* other non-node represented commands,
|
||||||
*
|
* like "-fdsev synt"
|
||||||
* A node can be of four types:
|
* @after_cmd_line: optional extra command line to be added
|
||||||
* - QNODE_MACHINE: for example "arm/raspi2"
|
* after the device command. This option
|
||||||
* - QNODE_DRIVER: for example "generic-sdhci"
|
* is used to add other devices
|
||||||
* - QNODE_INTERFACE: for example "sdhci" (interface for all "-sdhci" drivers)
|
* command line that depend on current node.
|
||||||
* an interface is not explicitly created, it will be auto-
|
* Automatically prepends " " to this argument
|
||||||
* matically instantiated when a node consumes or produces
|
* @edge_name: optional edge to differentiate multiple
|
||||||
* it.
|
* devices with same node name
|
||||||
* - QNODE_TEST: for example "sdhci-test", consumes an interface and tests
|
|
||||||
* the functions provided
|
|
||||||
*
|
|
||||||
* Notes for the nodes:
|
|
||||||
* - QNODE_MACHINE: each machine struct must have a QGuestAllocator and
|
|
||||||
* implement get_driver to return the allocator passing
|
|
||||||
* "memory". The function can also return NULL if the
|
|
||||||
* allocator is not set.
|
|
||||||
* - QNODE_DRIVER: driver names must be unique, and machines and nodes
|
|
||||||
* planned to be "consumed" by other nodes must match QEMU
|
|
||||||
* drivers name, otherwise they won't be discovered
|
|
||||||
*
|
|
||||||
* An edge relation between two nodes (drivers or machines) X and Y can be:
|
|
||||||
* - X CONSUMES Y: Y can be plugged into X
|
|
||||||
* - X PRODUCES Y: X provides the interface Y
|
|
||||||
* - X CONTAINS Y: Y is part of X component
|
|
||||||
*
|
|
||||||
* Basic framework steps are the following:
|
|
||||||
* - All nodes and edges are created in their respective
|
|
||||||
* machine/driver/test files
|
|
||||||
* - The framework starts QEMU and asks for a list of available devices
|
|
||||||
* and machines (note that only machines and "consumed" nodes are mapped
|
|
||||||
* 1:1 with QEMU devices)
|
|
||||||
* - The framework walks the graph starting from the available machines and
|
|
||||||
* performs a Depth First Search for tests
|
|
||||||
* - Once a test is found, the path is walked again and all drivers are
|
|
||||||
* allocated accordingly and the final interface is passed to the test
|
|
||||||
* - The test is executed
|
|
||||||
* - Unused objects are cleaned and the path discovery is continued
|
|
||||||
*
|
|
||||||
* Depending on the QEMU binary used, only some drivers/machines will be
|
|
||||||
* available and only test that are reached by them will be executed.
|
|
||||||
*
|
|
||||||
* <example>
|
|
||||||
* <title>Creating new driver an its interface</title>
|
|
||||||
* <programlisting>
|
|
||||||
#include "qgraph.h"
|
|
||||||
|
|
||||||
struct My_driver {
|
|
||||||
QOSGraphObject obj;
|
|
||||||
Node_produced prod;
|
|
||||||
Node_contained cont;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void my_destructor(QOSGraphObject *obj)
|
|
||||||
{
|
|
||||||
g_free(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void my_get_driver(void *object, const char *interface) {
|
|
||||||
My_driver *dev = object;
|
|
||||||
if (!g_strcmp0(interface, "my_interface")) {
|
|
||||||
return &dev->prod;
|
|
||||||
}
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void my_get_device(void *object, const char *device) {
|
|
||||||
My_driver *dev = object;
|
|
||||||
if (!g_strcmp0(device, "my_driver_contained")) {
|
|
||||||
return &dev->cont;
|
|
||||||
}
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *my_driver_constructor(void *node_consumed,
|
|
||||||
QOSGraphObject *alloc)
|
|
||||||
{
|
|
||||||
My_driver dev = g_new(My_driver, 1);
|
|
||||||
// get the node pointed by the produce edge
|
|
||||||
dev->obj.get_driver = my_get_driver;
|
|
||||||
// get the node pointed by the contains
|
|
||||||
dev->obj.get_device = my_get_device;
|
|
||||||
// free the object
|
|
||||||
dev->obj.destructor = my_destructor;
|
|
||||||
do_something_with_node_consumed(node_consumed);
|
|
||||||
// set all fields of contained device
|
|
||||||
init_contained_device(&dev->cont);
|
|
||||||
return &dev->obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void register_my_driver(void)
|
|
||||||
{
|
|
||||||
qos_node_create_driver("my_driver", my_driver_constructor);
|
|
||||||
// contained drivers don't need a constructor,
|
|
||||||
// they will be init by the parent.
|
|
||||||
qos_node_create_driver("my_driver_contained", NULL);
|
|
||||||
|
|
||||||
// For the sake of this example, assume machine x86_64/pc contains
|
|
||||||
// "other_node".
|
|
||||||
// This relation, along with the machine and "other_node" creation,
|
|
||||||
// should be defined in the x86_64_pc-machine.c file.
|
|
||||||
// "my_driver" will then consume "other_node"
|
|
||||||
qos_node_contains("my_driver", "my_driver_contained");
|
|
||||||
qos_node_produces("my_driver", "my_interface");
|
|
||||||
qos_node_consumes("my_driver", "other_node");
|
|
||||||
}
|
|
||||||
* </programlisting>
|
|
||||||
* </example>
|
|
||||||
*
|
|
||||||
* In the above example, all possible types of relations are created:
|
|
||||||
* node "my_driver" consumes, contains and produces other nodes.
|
|
||||||
* more specifically:
|
|
||||||
* x86_64/pc -->contains--> other_node <--consumes-- my_driver
|
|
||||||
* |
|
|
||||||
* my_driver_contained <--contains--+
|
|
||||||
* |
|
|
||||||
* my_interface <--produces--+
|
|
||||||
*
|
|
||||||
* or inverting the consumes edge in consumed_by:
|
|
||||||
*
|
|
||||||
* x86_64/pc -->contains--> other_node --consumed_by--> my_driver
|
|
||||||
* |
|
|
||||||
* my_driver_contained <--contains--+
|
|
||||||
* |
|
|
||||||
* my_interface <--produces--+
|
|
||||||
*
|
|
||||||
* <example>
|
|
||||||
* <title>Creating new test</title>
|
|
||||||
* <programlisting>
|
|
||||||
* #include "qgraph.h"
|
|
||||||
*
|
|
||||||
* static void my_test_function(void *obj, void *data)
|
|
||||||
* {
|
|
||||||
* Node_produced *interface_to_test = obj;
|
|
||||||
* // test interface_to_test
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* static void register_my_test(void)
|
|
||||||
* {
|
|
||||||
* qos_add_test("my_interface", "my_test", my_test_function);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* libqos_init(register_my_test);
|
|
||||||
*
|
|
||||||
* </programlisting>
|
|
||||||
* </example>
|
|
||||||
*
|
|
||||||
* Here a new test is created, consuming "my_interface" node
|
|
||||||
* and creating a valid path from a machine to a test.
|
|
||||||
* Final graph will be like this:
|
|
||||||
* x86_64/pc -->contains--> other_node <--consumes-- my_driver
|
|
||||||
* |
|
|
||||||
* my_driver_contained <--contains--+
|
|
||||||
* |
|
|
||||||
* my_test --consumes--> my_interface <--produces--+
|
|
||||||
*
|
|
||||||
* or inverting the consumes edge in consumed_by:
|
|
||||||
*
|
|
||||||
* x86_64/pc -->contains--> other_node --consumed_by--> my_driver
|
|
||||||
* |
|
|
||||||
* my_driver_contained <--contains--+
|
|
||||||
* |
|
|
||||||
* my_test <--consumed_by-- my_interface <--produces--+
|
|
||||||
*
|
|
||||||
* Assuming there the binary is
|
|
||||||
* QTEST_QEMU_BINARY=./qemu-system-x86_64
|
|
||||||
* a valid test path will be:
|
|
||||||
* "/x86_64/pc/other_node/my_driver/my_interface/my_test".
|
|
||||||
*
|
|
||||||
* Additional examples are also in test-qgraph.c
|
|
||||||
*
|
|
||||||
* Command line:
|
|
||||||
* Command line is built by using node names and optional arguments
|
|
||||||
* passed by the user when building the edges.
|
|
||||||
*
|
|
||||||
* There are three types of command line arguments:
|
|
||||||
* - in node : created from the node name. For example, machines will
|
|
||||||
* have "-M <machine>" to its command line, while devices
|
|
||||||
* "-device <device>". It is automatically done by the
|
|
||||||
* framework.
|
|
||||||
* - after node : added as additional argument to the node name.
|
|
||||||
* This argument is added optionally when creating edges,
|
|
||||||
* by setting the parameter @after_cmd_line and
|
|
||||||
* @extra_edge_opts in #QOSGraphEdgeOptions.
|
|
||||||
* The framework automatically adds
|
|
||||||
* a comma before @extra_edge_opts,
|
|
||||||
* because it is going to add attributes
|
|
||||||
* after the destination node pointed by
|
|
||||||
* the edge containing these options, and automatically
|
|
||||||
* adds a space before @after_cmd_line, because it
|
|
||||||
* adds an additional device, not an attribute.
|
|
||||||
* - before node : added as additional argument to the node name.
|
|
||||||
* This argument is added optionally when creating edges,
|
|
||||||
* by setting the parameter @before_cmd_line in
|
|
||||||
* #QOSGraphEdgeOptions. This attribute
|
|
||||||
* is going to add attributes before the destination node
|
|
||||||
* pointed by the edge containing these options. It is
|
|
||||||
* helpful to commands that are not node-representable,
|
|
||||||
* such as "-fdsev" or "-netdev".
|
|
||||||
*
|
|
||||||
* While adding command line in edges is always used, not all nodes names are
|
|
||||||
* used in every path walk: this is because the contained or produced ones
|
|
||||||
* are already added by QEMU, so only nodes that "consumes" will be used to
|
|
||||||
* build the command line. Also, nodes that will have { "abstract" : true }
|
|
||||||
* as QMP attribute will loose their command line, since they are not proper
|
|
||||||
* devices to be added in QEMU.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
*
|
|
||||||
QOSGraphEdgeOptions opts = {
|
|
||||||
.arg = NULL,
|
|
||||||
.size_arg = 0,
|
|
||||||
.after_cmd_line = "-device other",
|
|
||||||
.before_cmd_line = "-netdev something",
|
|
||||||
.extra_edge_opts = "addr=04.0",
|
|
||||||
};
|
|
||||||
QOSGraphNode * node = qos_node_create_driver("my_node", constructor);
|
|
||||||
qos_node_consumes_args("my_node", "interface", &opts);
|
|
||||||
*
|
|
||||||
* Will produce the following command line:
|
|
||||||
* "-netdev something -device my_node,addr=04.0 -device other"
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edge options to be passed to the contains/consumes *_args function.
|
|
||||||
*/
|
*/
|
||||||
struct QOSGraphEdgeOptions {
|
struct QOSGraphEdgeOptions {
|
||||||
void *arg; /*
|
void *arg;
|
||||||
* optional arg that will be used by
|
uint32_t size_arg;
|
||||||
* dest edge
|
const char *extra_device_opts;
|
||||||
*/
|
const char *before_cmd_line;
|
||||||
uint32_t size_arg; /*
|
const char *after_cmd_line;
|
||||||
* optional arg size that will be used by
|
const char *edge_name;
|
||||||
* dest edge
|
|
||||||
*/
|
|
||||||
const char *extra_device_opts;/*
|
|
||||||
*optional additional command line for dest
|
|
||||||
* edge, used to add additional attributes
|
|
||||||
* *after* the node command line, the
|
|
||||||
* framework automatically prepends ","
|
|
||||||
* to this argument.
|
|
||||||
*/
|
|
||||||
const char *before_cmd_line; /*
|
|
||||||
* optional additional command line for dest
|
|
||||||
* edge, used to add additional attributes
|
|
||||||
* *before* the node command line, usually
|
|
||||||
* other non-node represented commands,
|
|
||||||
* like "-fdsev synt"
|
|
||||||
*/
|
|
||||||
const char *after_cmd_line; /*
|
|
||||||
* optional extra command line to be added
|
|
||||||
* after the device command. This option
|
|
||||||
* is used to add other devices
|
|
||||||
* command line that depend on current node.
|
|
||||||
* Automatically prepends " " to this
|
|
||||||
* argument
|
|
||||||
*/
|
|
||||||
const char *edge_name; /*
|
|
||||||
* optional edge to differentiate multiple
|
|
||||||
* devices with same node name
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* struct QOSGraphTestOptions:
|
||||||
* Test options to be passed to the test functions.
|
* Test options to be passed to the test functions.
|
||||||
|
* @edge: edge arguments that will be used by test.
|
||||||
|
* Note that test *does not* use edge_name,
|
||||||
|
* and uses instead arg and size_arg as
|
||||||
|
* data arg for its test function.
|
||||||
|
* @arg: if @before is non-NULL, pass @arg there.
|
||||||
|
* Otherwise pass it to the test function.
|
||||||
|
* @before: executed before the test. Used to add
|
||||||
|
* additional parameters to the command line
|
||||||
|
* and modify the argument to the test function.
|
||||||
|
* @subprocess: run the test in a subprocess.
|
||||||
*/
|
*/
|
||||||
struct QOSGraphTestOptions {
|
struct QOSGraphTestOptions {
|
||||||
QOSGraphEdgeOptions edge; /* edge arguments that will be used by test.
|
QOSGraphEdgeOptions edge;
|
||||||
* Note that test *does not* use edge_name,
|
void *arg;
|
||||||
* and uses instead arg and size_arg as
|
QOSBeforeTest before;
|
||||||
* data arg for its test function.
|
bool subprocess;
|
||||||
*/
|
|
||||||
void *arg; /* passed to the .before function, or to the
|
|
||||||
* test function if there is no .before
|
|
||||||
* function
|
|
||||||
*/
|
|
||||||
QOSBeforeTest before; /* executed before the test. Can add
|
|
||||||
* additional parameters to the command line
|
|
||||||
* and modify the argument to the test function.
|
|
||||||
*/
|
|
||||||
bool subprocess; /* run the test in a subprocess */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* struct QOSGraphObject:
|
||||||
* Each driver, test or machine of this framework will have a
|
* Each driver, test or machine of this framework will have a
|
||||||
* QOSGraphObject as first field.
|
* QOSGraphObject as first field.
|
||||||
*
|
*
|
||||||
* This set of functions offered by QOSGraphObject are executed
|
* This set of functions offered by QOSGraphObject are executed
|
||||||
* in different stages of the framework:
|
* in different stages of the framework:
|
||||||
* - get_driver / get_device : Once a machine-to-test path has been
|
* @get_driver: see @get_device
|
||||||
* found, the framework traverses it again and allocates all the
|
* @get_device: Once a machine-to-test path has been
|
||||||
* nodes, using the provided constructor. To satisfy their relations,
|
* found, the framework traverses it again and allocates all the
|
||||||
* i.e. for produces or contains, where a struct constructor needs
|
* nodes, using the provided constructor. To satisfy their
|
||||||
* an external parameter represented by the previous node,
|
* relations, i.e. for produces or contains, where a struct
|
||||||
* the framework will call get_device (for contains) or
|
* constructor needs an external parameter represented by the
|
||||||
* get_driver (for produces), depending on the edge type, passing
|
* previous node, the framework will call
|
||||||
* them the name of the next node to be taken and getting from them
|
* @get_device (for contains) or @get_driver (for produces),
|
||||||
* the corresponding pointer to the actual structure of the next node to
|
* depending on the edge type, passing them the name of the next
|
||||||
* be used in the path.
|
* node to be taken and getting from them the corresponding
|
||||||
*
|
* pointer to the actual structure of the next node to
|
||||||
* - start_hw: This function is executed after all the path objects
|
* be used in the path.
|
||||||
* have been allocated, but before the test is run. It starts the hw, setting
|
* @start_hw: This function is executed after all the path objects
|
||||||
* the initial configurations (*_device_enable) and making it ready for the
|
* have been allocated, but before the test is run. It starts the
|
||||||
* test.
|
* hw, setting the initial configurations (\*_device_enable) and
|
||||||
*
|
* making it ready for the test.
|
||||||
* - destructor: Opposite to the node constructor, destroys the object.
|
* @destructor: Opposite to the node constructor, destroys the object.
|
||||||
* This function is called after the test has been executed, and performs
|
* This function is called after the test has been executed, and
|
||||||
* a complete cleanup of each node allocated field. In case no constructor
|
* performs a complete cleanup of each node allocated field.
|
||||||
* is provided, no destructor will be called.
|
* In case no constructor is provided, no destructor will be
|
||||||
*
|
* called.
|
||||||
|
* @free: free the memory associated to the QOSGraphObject and its contained
|
||||||
|
* children
|
||||||
*/
|
*/
|
||||||
struct QOSGraphObject {
|
struct QOSGraphObject {
|
||||||
/* for produces edges, returns void * */
|
|
||||||
QOSGetDriver get_driver;
|
QOSGetDriver get_driver;
|
||||||
/* for contains edges, returns a QOSGraphObject * */
|
|
||||||
QOSGetDevice get_device;
|
QOSGetDevice get_device;
|
||||||
/* start the hw, get ready for the test */
|
|
||||||
QOSStartFunct start_hw;
|
QOSStartFunct start_hw;
|
||||||
/* destroy this QOSGraphObject */
|
|
||||||
QOSDestructorFunc destructor;
|
QOSDestructorFunc destructor;
|
||||||
/* free the memory associated to the QOSGraphObject and its contained
|
|
||||||
* children */
|
|
||||||
GDestroyNotify free;
|
GDestroyNotify free;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -399,24 +152,30 @@ void qos_graph_init(void);
|
|||||||
void qos_graph_destroy(void);
|
void qos_graph_destroy(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qos_node_destroy(): removes and frees a node from the,
|
* qos_node_destroy(): removes and frees a node from the
|
||||||
* nodes hash table.
|
* nodes hash table.
|
||||||
|
* @key: Name of the node
|
||||||
*/
|
*/
|
||||||
void qos_node_destroy(void *key);
|
void qos_node_destroy(void *key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qos_edge_destroy(): removes and frees an edge from the,
|
* qos_edge_destroy(): removes and frees an edge from the
|
||||||
* edges hash table.
|
* edges hash table.
|
||||||
|
* @key: Name of the node
|
||||||
*/
|
*/
|
||||||
void qos_edge_destroy(void *key);
|
void qos_edge_destroy(void *key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qos_add_test(): adds a test node @name to the nodes hash table.
|
* qos_add_test(): adds a test node @name to the nodes hash table.
|
||||||
|
* @name: Name of the test
|
||||||
|
* @interface: Name of the interface node it consumes
|
||||||
|
* @test_func: Actual test to perform
|
||||||
|
* @opts: Facultative options (see %QOSGraphTestOptions)
|
||||||
*
|
*
|
||||||
* The test will consume a @interface node, and once the
|
* The test will consume a @interface node, and once the
|
||||||
* graph walking algorithm has found it, the @test_func will be
|
* graph walking algorithm has found it, the @test_func will be
|
||||||
* executed. It also has the possibility to
|
* executed. It also has the possibility to
|
||||||
* add an optional @opts (see %QOSGraphNodeOptions).
|
* add an optional @opts (see %QOSGraphTestOptions).
|
||||||
*
|
*
|
||||||
* For tests, opts->edge.arg and size_arg represent the arg to pass
|
* For tests, opts->edge.arg and size_arg represent the arg to pass
|
||||||
* to @test_func
|
* to @test_func
|
||||||
@ -428,6 +187,8 @@ void qos_add_test(const char *name, const char *interface,
|
|||||||
/**
|
/**
|
||||||
* qos_node_create_machine(): creates the machine @name and
|
* qos_node_create_machine(): creates the machine @name and
|
||||||
* adds it to the node hash table.
|
* adds it to the node hash table.
|
||||||
|
* @name: Name of the machine
|
||||||
|
* @function: Machine constructor
|
||||||
*
|
*
|
||||||
* This node will be of type QNODE_MACHINE and have @function
|
* This node will be of type QNODE_MACHINE and have @function
|
||||||
* as constructor
|
* as constructor
|
||||||
@ -438,6 +199,9 @@ void qos_node_create_machine(const char *name, QOSCreateMachineFunc function);
|
|||||||
* qos_node_create_machine_args(): same as qos_node_create_machine,
|
* qos_node_create_machine_args(): same as qos_node_create_machine,
|
||||||
* but with the possibility to add an optional ", @opts" after -M machine
|
* but with the possibility to add an optional ", @opts" after -M machine
|
||||||
* command line.
|
* command line.
|
||||||
|
* @name: Name of the machine
|
||||||
|
* @function: Machine constructor
|
||||||
|
* @opts: Optional additional command line
|
||||||
*/
|
*/
|
||||||
void qos_node_create_machine_args(const char *name,
|
void qos_node_create_machine_args(const char *name,
|
||||||
QOSCreateMachineFunc function,
|
QOSCreateMachineFunc function,
|
||||||
@ -446,6 +210,8 @@ void qos_node_create_machine_args(const char *name,
|
|||||||
/**
|
/**
|
||||||
* qos_node_create_driver(): creates the driver @name and
|
* qos_node_create_driver(): creates the driver @name and
|
||||||
* adds it to the node hash table.
|
* adds it to the node hash table.
|
||||||
|
* @name: Name of the driver
|
||||||
|
* @function: Driver constructor
|
||||||
*
|
*
|
||||||
* This node will be of type QNODE_DRIVER and have @function
|
* This node will be of type QNODE_DRIVER and have @function
|
||||||
* as constructor
|
* as constructor
|
||||||
@ -453,17 +219,17 @@ void qos_node_create_machine_args(const char *name,
|
|||||||
void qos_node_create_driver(const char *name, QOSCreateDriverFunc function);
|
void qos_node_create_driver(const char *name, QOSCreateDriverFunc function);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Behaves as qos_node_create_driver() with the extension of allowing to
|
* qos_node_create_driver_named(): behaves as qos_node_create_driver() with the
|
||||||
* specify a different node name vs. associated QEMU device name.
|
* extension of allowing to specify a different node name vs. associated QEMU
|
||||||
|
* device name.
|
||||||
|
* @name: Custom, unique name of the node to be created
|
||||||
|
* @qemu_name: Actual (official) QEMU driver name the node shall be
|
||||||
|
* associated with
|
||||||
|
* @function: Driver constructor
|
||||||
*
|
*
|
||||||
* Use this function instead of qos_node_create_driver() if you need to create
|
* Use this function instead of qos_node_create_driver() if you need to create
|
||||||
* several instances of the same QEMU device. You are free to choose a custom
|
* several instances of the same QEMU device. You are free to choose a custom
|
||||||
* node name, however the chosen node name must always be unique.
|
* node name, however the chosen node name must always be unique.
|
||||||
*
|
|
||||||
* @param name: custom, unique name of the node to be created
|
|
||||||
* @param qemu_name: actual (official) QEMU driver name the node shall be
|
|
||||||
* associated with
|
|
||||||
* @param function: driver constructor
|
|
||||||
*/
|
*/
|
||||||
void qos_node_create_driver_named(const char *name, const char *qemu_name,
|
void qos_node_create_driver_named(const char *name, const char *qemu_name,
|
||||||
QOSCreateDriverFunc function);
|
QOSCreateDriverFunc function);
|
||||||
@ -472,6 +238,9 @@ void qos_node_create_driver_named(const char *name, const char *qemu_name,
|
|||||||
* qos_node_contains(): creates one or more edges of type QEDGE_CONTAINS
|
* qos_node_contains(): creates one or more edges of type QEDGE_CONTAINS
|
||||||
* and adds them to the edge list mapped to @container in the
|
* and adds them to the edge list mapped to @container in the
|
||||||
* edge hash table.
|
* edge hash table.
|
||||||
|
* @container: Source node that "contains"
|
||||||
|
* @contained: Destination node that "is contained"
|
||||||
|
* @opts: Facultative options (see %QOSGraphEdgeOptions)
|
||||||
*
|
*
|
||||||
* The edges will have @container as source and @contained as destination.
|
* The edges will have @container as source and @contained as destination.
|
||||||
*
|
*
|
||||||
@ -483,14 +252,17 @@ void qos_node_create_driver_named(const char *name, const char *qemu_name,
|
|||||||
* This function can be useful when there are multiple devices
|
* This function can be useful when there are multiple devices
|
||||||
* with the same node name contained in a machine/other node
|
* with the same node name contained in a machine/other node
|
||||||
*
|
*
|
||||||
* For example, if "arm/raspi2" contains 2 "generic-sdhci"
|
* For example, if ``arm/raspi2`` contains 2 ``generic-sdhci``
|
||||||
* devices, the right commands will be:
|
* devices, the right commands will be:
|
||||||
* qos_node_create_machine("arm/raspi2");
|
*
|
||||||
* qos_node_create_driver("generic-sdhci", constructor);
|
* .. code::
|
||||||
* //assume rest of the fields are set NULL
|
*
|
||||||
* QOSGraphEdgeOptions op1 = { .edge_name = "emmc" };
|
* qos_node_create_machine("arm/raspi2");
|
||||||
* QOSGraphEdgeOptions op2 = { .edge_name = "sdcard" };
|
* qos_node_create_driver("generic-sdhci", constructor);
|
||||||
* qos_node_contains("arm/raspi2", "generic-sdhci", &op1, &op2, NULL);
|
* // assume rest of the fields are set NULL
|
||||||
|
* QOSGraphEdgeOptions op1 = { .edge_name = "emmc" };
|
||||||
|
* QOSGraphEdgeOptions op2 = { .edge_name = "sdcard" };
|
||||||
|
* qos_node_contains("arm/raspi2", "generic-sdhci", &op1, &op2, NULL);
|
||||||
*
|
*
|
||||||
* Of course this also requires that the @container's get_device function
|
* Of course this also requires that the @container's get_device function
|
||||||
* should implement a case for "emmc" and "sdcard".
|
* should implement a case for "emmc" and "sdcard".
|
||||||
@ -505,6 +277,8 @@ void qos_node_contains(const char *container, const char *contained,
|
|||||||
* qos_node_produces(): creates an edge of type QEDGE_PRODUCES and
|
* qos_node_produces(): creates an edge of type QEDGE_PRODUCES and
|
||||||
* adds it to the edge list mapped to @producer in the
|
* adds it to the edge list mapped to @producer in the
|
||||||
* edge hash table.
|
* edge hash table.
|
||||||
|
* @producer: Source node that "produces"
|
||||||
|
* @interface: Interface node that "is produced"
|
||||||
*
|
*
|
||||||
* This edge will have @producer as source and @interface as destination.
|
* This edge will have @producer as source and @interface as destination.
|
||||||
*/
|
*/
|
||||||
@ -514,6 +288,9 @@ void qos_node_produces(const char *producer, const char *interface);
|
|||||||
* qos_node_consumes(): creates an edge of type QEDGE_CONSUMED_BY and
|
* qos_node_consumes(): creates an edge of type QEDGE_CONSUMED_BY and
|
||||||
* adds it to the edge list mapped to @interface in the
|
* adds it to the edge list mapped to @interface in the
|
||||||
* edge hash table.
|
* edge hash table.
|
||||||
|
* @consumer: Node that "consumes"
|
||||||
|
* @interface: Interface node that "is consumed by"
|
||||||
|
* @opts: Facultative options (see %QOSGraphEdgeOptions)
|
||||||
*
|
*
|
||||||
* This edge will have @interface as source and @consumer as destination.
|
* This edge will have @interface as source and @consumer as destination.
|
||||||
* It also has the possibility to add an optional @opts
|
* It also has the possibility to add an optional @opts
|
||||||
@ -539,7 +316,7 @@ const char *qos_get_current_command_line(void);
|
|||||||
/**
|
/**
|
||||||
* qos_allocate_objects():
|
* qos_allocate_objects():
|
||||||
* @qts: The #QTestState that will be referred to by the machine object.
|
* @qts: The #QTestState that will be referred to by the machine object.
|
||||||
* @alloc: Where to store the allocator for the machine object, or %NULL.
|
* @p_alloc: Where to store the allocator for the machine object, or %NULL.
|
||||||
*
|
*
|
||||||
* Allocate driver objects for the current test
|
* Allocate driver objects for the current test
|
||||||
* path, but relative to the QTestState @qts.
|
* path, but relative to the QTestState @qts.
|
||||||
@ -551,24 +328,27 @@ void *qos_allocate_objects(QTestState *qts, QGuestAllocator **p_alloc);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* qos_object_destroy(): calls the destructor for @obj
|
* qos_object_destroy(): calls the destructor for @obj
|
||||||
|
* @obj: A #QOSGraphObject to destroy
|
||||||
*/
|
*/
|
||||||
void qos_object_destroy(QOSGraphObject *obj);
|
void qos_object_destroy(QOSGraphObject *obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qos_object_queue_destroy(): queue the destructor for @obj so that it is
|
* qos_object_queue_destroy(): queue the destructor for @obj so that it is
|
||||||
* called at the end of the test
|
* called at the end of the test
|
||||||
|
* @obj: A #QOSGraphObject to destroy
|
||||||
*/
|
*/
|
||||||
void qos_object_queue_destroy(QOSGraphObject *obj);
|
void qos_object_queue_destroy(QOSGraphObject *obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qos_object_start_hw(): calls the start_hw function for @obj
|
* qos_object_start_hw(): calls the start_hw function for @obj
|
||||||
|
* @obj: A #QOSGraphObject containing the start_hw function
|
||||||
*/
|
*/
|
||||||
void qos_object_start_hw(QOSGraphObject *obj);
|
void qos_object_start_hw(QOSGraphObject *obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qos_machine_new(): instantiate a new machine node
|
* qos_machine_new(): instantiate a new machine node
|
||||||
* @node: A machine node to be instantiated
|
* @node: Machine node to be instantiated
|
||||||
* @qts: The #QTestState that will be referred to by the machine object.
|
* @qts: A #QTestState that will be referred to by the machine object.
|
||||||
*
|
*
|
||||||
* Returns a machine object.
|
* Returns a machine object.
|
||||||
*/
|
*/
|
||||||
@ -587,8 +367,8 @@ QOSGraphObject *qos_driver_new(QOSGraphNode *node, QOSGraphObject *parent,
|
|||||||
QGuestAllocator *alloc, void *arg);
|
QGuestAllocator *alloc, void *arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Just for debugging purpose: prints all currently existing nodes and
|
* qos_dump_graph(): prints all currently existing nodes and
|
||||||
* edges to stdout.
|
* edges to stdout. Just for debugging purposes.
|
||||||
*
|
*
|
||||||
* All qtests add themselves to the overall qos graph by calling qgraph
|
* All qtests add themselves to the overall qos graph by calling qgraph
|
||||||
* functions that add device nodes and edges between the individual graph
|
* functions that add device nodes and edges between the individual graph
|
||||||
|
Loading…
Reference in New Issue
Block a user