From 48b28b6aec23b82c0239aee60af2a470c06dde1a Mon Sep 17 00:00:00 2001 From: Xu Wang Date: Mon, 17 Mar 2014 19:21:23 -0400 Subject: [PATCH 51/60] Parse/Store controller XML tags Parse and store the 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 "" 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 --- 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 @@ -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 @@ -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