You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
401 lines
14 KiB
401 lines
14 KiB
7 years ago
|
From 48b28b6aec23b82c0239aee60af2a470c06dde1a Mon Sep 17 00:00:00 2001
|
||
|
From: Xu Wang <gesaint@linux.vnet.ibm.com>
|
||
|
Date: Mon, 17 Mar 2014 19:21:23 -0400
|
||
|
Subject: [PATCH 51/60] Parse/Store controller XML tags
|
||
|
|
||
|
Parse and store the <controller> XML tags. The generated DeviceID will
|
||
|
be a combination of "controller" + XML device "name" + XML Index "value".
|
||
|
This should be unique enough now and generates "controller:pci:0" or
|
||
|
"controller:usb:0" DeviceID's.
|
||
|
|
||
|
In the future, if support is added for the "<master>" XML child a new
|
||
|
mechanism will need to be put in place since one of those controllers is
|
||
|
designed to have the same name and index - what changes is the function
|
||
|
for the device.
|
||
|
|
||
|
Signed-off-by: John Ferlan <jferlan@redhat.com>
|
||
|
---
|
||
|
libxkutil/device_parsing.c | 119 ++++++++++++++++++++++++++++++++++++++++++++-
|
||
|
libxkutil/xmlgen.c | 74 +++++++++++++++++++++++++++-
|
||
|
2 files changed, 191 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c
|
||
|
index d2d3859..f863cc5 100644
|
||
|
--- a/libxkutil/device_parsing.c
|
||
|
+++ b/libxkutil/device_parsing.c
|
||
|
@@ -1,5 +1,5 @@
|
||
|
/*
|
||
|
- * Copyright IBM Corp. 2007, 2013
|
||
|
+ * Copyright IBM Corp. 2007-2014
|
||
|
*
|
||
|
* Authors:
|
||
|
* Dan Smith <danms@us.ibm.com>
|
||
|
@@ -49,6 +49,7 @@
|
||
|
#define GRAPHICS_XPATH (xmlChar *)"/domain/devices/graphics | "\
|
||
|
"/domain/devices/console"
|
||
|
#define INPUT_XPATH (xmlChar *)"/domain/devices/input"
|
||
|
+#define CONTROLLER_XPATH (xmlChar *)"/domain/devices/controller"
|
||
|
|
||
|
#define DEFAULT_BRIDGE "xenbr0"
|
||
|
#define DEFAULT_NETWORK "default"
|
||
|
@@ -69,6 +70,7 @@ static void cleanup_device_address(struct device_address *addr)
|
||
|
if (addr == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Cleanup %d addresses", addr->ct);
|
||
|
for (i = 0; i < addr->ct; i++) {
|
||
|
free(addr->key[i]);
|
||
|
free(addr->value[i]);
|
||
|
@@ -84,6 +86,7 @@ static void cleanup_disk_device(struct disk_device *dev)
|
||
|
if (dev == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Clean Disk type %s", dev->type);
|
||
|
free(dev->type);
|
||
|
free(dev->device);
|
||
|
free(dev->driver);
|
||
|
@@ -103,6 +106,7 @@ static void cleanup_vsi_device(struct vsi_device *dev)
|
||
|
if (dev == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Clean VSI type %s", dev->vsi_type);
|
||
|
free(dev->vsi_type);
|
||
|
free(dev->manager_id);
|
||
|
free(dev->type_id);
|
||
|
@@ -117,6 +121,7 @@ static void cleanup_net_device(struct net_device *dev)
|
||
|
if (dev == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Clean net type %s", dev->type);
|
||
|
free(dev->type);
|
||
|
free(dev->mac);
|
||
|
free(dev->source);
|
||
|
@@ -134,6 +139,7 @@ static void cleanup_emu_device(struct emu_device *dev)
|
||
|
if (dev == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Clean emu %s", dev->path);
|
||
|
free(dev->path);
|
||
|
}
|
||
|
|
||
|
@@ -157,6 +163,7 @@ static void cleanup_graphics_device(struct graphics_device *dev)
|
||
|
if (dev == NULL || dev->type == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Clean graphics type %s", dev->type);
|
||
|
if (STREQC(dev->type, "sdl"))
|
||
|
cleanup_sdl_device(dev);
|
||
|
else
|
||
|
@@ -170,6 +177,7 @@ static void cleanup_path_device(struct path_device *dev)
|
||
|
if (dev == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Clean path device %s", dev->path);
|
||
|
free(dev->path);
|
||
|
|
||
|
}
|
||
|
@@ -179,6 +187,7 @@ static void cleanup_unixsock_device(struct unixsock_device *dev)
|
||
|
if (dev == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Clean unixsock device");
|
||
|
free(dev->path);
|
||
|
free(dev->mode);
|
||
|
|
||
|
@@ -189,6 +198,7 @@ static void cleanup_tcp_device(struct tcp_device *dev)
|
||
|
if (dev == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Clean tcp device");
|
||
|
free(dev->mode);
|
||
|
free(dev->protocol);
|
||
|
free(dev->host);
|
||
|
@@ -201,6 +211,7 @@ static void cleanup_udp_device(struct udp_device *dev)
|
||
|
if (dev == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Clean udb bind device");
|
||
|
free(dev->bind_host);
|
||
|
free(dev->bind_service);
|
||
|
free(dev->connect_host);
|
||
|
@@ -212,6 +223,7 @@ static void cleanup_console_device(struct console_device *dev)
|
||
|
if (dev == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Clean console source_type %d", dev->source_type);
|
||
|
switch (dev->source_type)
|
||
|
{
|
||
|
case CIM_CHARDEV_SOURCE_TYPE_PTY:
|
||
|
@@ -304,10 +316,24 @@ static void cleanup_input_device(struct input_device *dev)
|
||
|
if (dev == NULL)
|
||
|
return;
|
||
|
|
||
|
+ CU_DEBUG("Clean input device %s", dev->type);
|
||
|
free(dev->type);
|
||
|
free(dev->bus);
|
||
|
}
|
||
|
|
||
|
+static void cleanup_controller_device(struct controller_device *dev)
|
||
|
+{
|
||
|
+ if (dev == NULL)
|
||
|
+ return;
|
||
|
+
|
||
|
+ CU_DEBUG("Clean controller device %d", dev->type);
|
||
|
+ free(dev->model);
|
||
|
+ free(dev->queues);
|
||
|
+ free(dev->ports);
|
||
|
+ free(dev->vectors);
|
||
|
+ cleanup_device_address(&dev->address);
|
||
|
+}
|
||
|
+
|
||
|
void cleanup_virt_device(struct virt_device *dev)
|
||
|
{
|
||
|
if (dev == NULL)
|
||
|
@@ -325,6 +351,8 @@ void cleanup_virt_device(struct virt_device *dev)
|
||
|
cleanup_input_device(&dev->dev.input);
|
||
|
else if (dev->type == CIM_RES_TYPE_CONSOLE)
|
||
|
cleanup_console_device(&dev->dev.console);
|
||
|
+ else if (dev->type == CIM_RES_TYPE_CONTROLLER)
|
||
|
+ cleanup_controller_device(&dev->dev.controller);
|
||
|
|
||
|
free(dev->id);
|
||
|
|
||
|
@@ -339,6 +367,7 @@ void cleanup_virt_devices(struct virt_device **_devs, int count)
|
||
|
for (i = 0; i < count; i++)
|
||
|
cleanup_virt_device(&devs[i]);
|
||
|
|
||
|
+ CU_DEBUG("All devices cleaned");
|
||
|
free(devs);
|
||
|
*_devs = NULL;
|
||
|
}
|
||
|
@@ -1107,6 +1136,75 @@ static int parse_input_device(xmlNode *node, struct virt_device **vdevs)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static int parse_controller_device(xmlNode *cnode, struct virt_device **vdevs)
|
||
|
+{
|
||
|
+ struct virt_device *vdev = NULL;
|
||
|
+ struct controller_device *cdev = NULL;
|
||
|
+ char *type_str = NULL;
|
||
|
+ xmlNode *child = NULL;
|
||
|
+ char *index = NULL;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ vdev = calloc(1, sizeof(*vdev));
|
||
|
+ if (vdev == NULL)
|
||
|
+ goto err;
|
||
|
+
|
||
|
+ cdev = &(vdev->dev.controller);
|
||
|
+
|
||
|
+ type_str = get_attr_value(cnode, "type");
|
||
|
+ if (type_str == NULL) {
|
||
|
+ CU_DEBUG("No type");
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+ CU_DEBUG("controller device type = %s", type_str);
|
||
|
+ cdev->type = controller_protocol_type_StrToID(type_str);
|
||
|
+ if (cdev->type == CIM_CONTROLLER_PROTOCOL_TYPE_UNKNOWN) {
|
||
|
+ CU_DEBUG("Unknown controller protocol type (%d)", cdev->type);
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ index = get_attr_value(cnode, "index");
|
||
|
+ if (index != NULL) {
|
||
|
+ sscanf(index, "%" PRIu64, &cdev->index);
|
||
|
+ free(index);
|
||
|
+ } else {
|
||
|
+ CU_DEBUG("No index");
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ cdev->model = get_attr_value(cnode, "model");
|
||
|
+ cdev->ports = get_attr_value(cnode, "ports");
|
||
|
+ cdev->vectors = get_attr_value(cnode, "vectors");
|
||
|
+
|
||
|
+ for (child = cnode->children; child != NULL; child = child->next) {
|
||
|
+ if (XSTREQ(child->name, "address")) {
|
||
|
+ parse_device_address(child, &cdev->address);
|
||
|
+ } else if (XSTREQ(child->name, "driver")) {
|
||
|
+ cdev->queues = get_attr_value(child, "queues");
|
||
|
+ }
|
||
|
+ }
|
||
|
+ vdev->type = CIM_RES_TYPE_CONTROLLER;
|
||
|
+
|
||
|
+ ret = asprintf(&vdev->id, "controller:%s:%" PRIu64,
|
||
|
+ type_str, cdev->index);
|
||
|
+ if (ret == -1) {
|
||
|
+ CU_DEBUG("Failed to create controller id string");
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+ CU_DEBUG("Controller id is %s", vdev->id);
|
||
|
+ free(type_str);
|
||
|
+
|
||
|
+ *vdevs = vdev;
|
||
|
+
|
||
|
+ return 1;
|
||
|
+ err:
|
||
|
+ free(type_str);
|
||
|
+ cleanup_controller_device(cdev);
|
||
|
+ free(vdev);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
static bool resize_devlist(struct virt_device **list, int newsize)
|
||
|
{
|
||
|
struct virt_device *_list;
|
||
|
@@ -1230,6 +1328,11 @@ static int parse_devices(const char *xml, struct virt_device **_list, int type)
|
||
|
func = &parse_input_device;
|
||
|
break;
|
||
|
|
||
|
+ case CIM_RES_TYPE_CONTROLLER:
|
||
|
+ xpathstr = CONTROLLER_XPATH;
|
||
|
+ func = &parse_controller_device;
|
||
|
+ break;
|
||
|
+
|
||
|
default:
|
||
|
CU_DEBUG("Unrecognized device type. Returning.");
|
||
|
goto err1;
|
||
|
@@ -1351,7 +1454,17 @@ struct virt_device *virt_device_dup(struct virt_device *_dev)
|
||
|
} else if (dev->type == CIM_RES_TYPE_CONSOLE) {
|
||
|
console_device_dup(&dev->dev.console,
|
||
|
&_dev->dev.console);
|
||
|
+ } else if (dev->type == CIM_RES_TYPE_CONTROLLER) {
|
||
|
+ dev->dev.controller.type = _dev->dev.controller.type;
|
||
|
+ dev->dev.controller.index = _dev->dev.controller.index;
|
||
|
+ DUP_FIELD(dev, _dev, dev.controller.model);
|
||
|
+ DUP_FIELD(dev, _dev, dev.controller.ports);
|
||
|
+ DUP_FIELD(dev, _dev, dev.controller.vectors);
|
||
|
+ DUP_FIELD(dev, _dev, dev.controller.queues);
|
||
|
+ duplicate_device_address(&dev->dev.controller.address,
|
||
|
+ &_dev->dev.controller.address);
|
||
|
}
|
||
|
+
|
||
|
return dev;
|
||
|
}
|
||
|
|
||
|
@@ -1731,6 +1844,9 @@ int get_dominfo_from_xml(const char *xml, struct domain **dominfo)
|
||
|
(*dominfo)->dev_vcpu_ct = parse_devices(xml,
|
||
|
&(*dominfo)->dev_vcpu,
|
||
|
CIM_RES_TYPE_PROC);
|
||
|
+ (*dominfo)->dev_controller_ct = parse_devices(xml,
|
||
|
+ &(*dominfo)->dev_controller,
|
||
|
+ CIM_RES_TYPE_CONTROLLER);
|
||
|
|
||
|
return ret;
|
||
|
|
||
|
@@ -1819,6 +1935,7 @@ void cleanup_dominfo(struct domain **dominfo)
|
||
|
cleanup_virt_devices(&dom->dev_graphics, dom->dev_graphics_ct);
|
||
|
cleanup_virt_devices(&dom->dev_input, dom->dev_input_ct);
|
||
|
cleanup_virt_devices(&dom->dev_console, dom->dev_console_ct);
|
||
|
+ cleanup_virt_devices(&dom->dev_controller, dom->dev_controller_ct);
|
||
|
|
||
|
free(dom);
|
||
|
|
||
|
diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
|
||
|
index 18c4765..3174ca9 100644
|
||
|
--- a/libxkutil/xmlgen.c
|
||
|
+++ b/libxkutil/xmlgen.c
|
||
|
@@ -1,5 +1,5 @@
|
||
|
/*
|
||
|
- * Copyright IBM Corp. 2007, 2013
|
||
|
+ * Copyright IBM Corp. 2007-2014
|
||
|
*
|
||
|
* Authors:
|
||
|
* Dan Smith <danms@us.ibm.com>
|
||
|
@@ -798,6 +798,72 @@ static const char *input_xml(xmlNodePtr root, struct domain *dominfo)
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
+static const char *controller_xml(xmlNodePtr root, struct domain *dominfo)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+ const char *msg = NULL;
|
||
|
+
|
||
|
+ CU_DEBUG("Found %d controllers", dominfo->dev_controller_ct);
|
||
|
+ for (i = 0; i < dominfo->dev_controller_ct; i++) {
|
||
|
+ xmlNodePtr ctlr;
|
||
|
+ xmlNodePtr tmp;
|
||
|
+ char *type_str;
|
||
|
+
|
||
|
+ struct virt_device *_dev = &dominfo->dev_controller[i];
|
||
|
+ if (_dev->type == CIM_RES_TYPE_UNKNOWN)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ struct controller_device *cdev = &_dev->dev.controller;
|
||
|
+
|
||
|
+ ctlr = xmlNewChild(root, NULL, BAD_CAST "controller", NULL);
|
||
|
+ if (ctlr == NULL)
|
||
|
+ return XML_ERROR;
|
||
|
+
|
||
|
+
|
||
|
+ type_str = controller_protocol_type_IDToStr(cdev->type);
|
||
|
+ if (type_str == NULL)
|
||
|
+ return XML_ERROR;
|
||
|
+
|
||
|
+ CU_DEBUG("Type=%s Index=%" PRIu64, type_str, cdev->index);
|
||
|
+ xmlNewProp(ctlr, BAD_CAST "type",
|
||
|
+ BAD_CAST type_str);
|
||
|
+
|
||
|
+ /* If index is missing, let libvirt generate it */
|
||
|
+ if (cdev->index != CONTROLLER_INDEX_NOT_SET) {
|
||
|
+ char *index;
|
||
|
+ if (asprintf(&index, "%" PRIu64, cdev->index) == -1)
|
||
|
+ return XML_ERROR;
|
||
|
+ xmlNewProp(ctlr, BAD_CAST "index", BAD_CAST index);
|
||
|
+ free(index);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Optional */
|
||
|
+ if (cdev->model)
|
||
|
+ xmlNewProp(ctlr, BAD_CAST "model",
|
||
|
+ BAD_CAST cdev->model);
|
||
|
+ if (cdev->ports)
|
||
|
+ xmlNewProp(ctlr, BAD_CAST "ports",
|
||
|
+ BAD_CAST cdev->ports);
|
||
|
+ if (cdev->vectors)
|
||
|
+ xmlNewProp(ctlr, BAD_CAST "vectors",
|
||
|
+ BAD_CAST cdev->vectors);
|
||
|
+ if (cdev->queues) {
|
||
|
+ tmp = xmlNewChild(ctlr, NULL, BAD_CAST "driver", NULL);
|
||
|
+ xmlNewProp(tmp, BAD_CAST "queueus",
|
||
|
+ BAD_CAST cdev->queues);
|
||
|
+ }
|
||
|
+ if (cdev->address.ct > 0) {
|
||
|
+ msg = device_address_xml(ctlr, &cdev->address);
|
||
|
+ if (msg != NULL) {
|
||
|
+ CU_DEBUG("Failed to set the address");
|
||
|
+ return msg;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
static char *system_xml(xmlNodePtr root, struct domain *domain)
|
||
|
{
|
||
|
xmlNodePtr tmp;
|
||
|
@@ -1129,6 +1195,11 @@ char *device_to_xml(struct virt_device *_dev)
|
||
|
dominfo->dev_input_ct = 1;
|
||
|
dominfo->dev_input = dev;
|
||
|
break;
|
||
|
+ case CIM_RES_TYPE_CONTROLLER:
|
||
|
+ func = controller_xml;
|
||
|
+ dominfo->dev_controller_ct = 1;
|
||
|
+ dominfo->dev_controller = dev;
|
||
|
+ break;
|
||
|
default:
|
||
|
cleanup_virt_devices(&dev, 1);
|
||
|
goto out;
|
||
|
@@ -1167,6 +1238,7 @@ char *system_to_xml(struct domain *dominfo)
|
||
|
&console_xml,
|
||
|
&graphics_xml,
|
||
|
&emu_xml,
|
||
|
+ &controller_xml,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
--
|
||
|
2.1.0
|