targetType only tracks the actual <target> format we are parsing. Currently we only fill abide this value for channel devices. Signed-off-by: Cole Robinson <crobinso@xxxxxxxxxx> --- src/conf/domain_conf.c | 379 +++++++++++++++++++++++++++++------------------ src/conf/domain_conf.h | 17 ++- src/qemu/qemu_conf.c | 6 +- 3 files changed, 249 insertions(+), 153 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index faf1629..6dde832 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -164,14 +164,17 @@ VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST, "internal", "direct") +VIR_ENUM_IMPL(virDomainChrChannelTarget, + VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST, + "guestfwd", + "virtio") + VIR_ENUM_IMPL(virDomainChrDevice, VIR_DOMAIN_CHR_DEVICE_TYPE_LAST, - "null", "monitor", "parallel", "serial", "console", - "guestfwd", - "virtio") + "channel") VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST, "null", @@ -524,12 +527,19 @@ void virDomainChrDefFree(virDomainChrDefPtr def) return; switch (def->deviceType) { - case VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD: - VIR_FREE(def->target.addr); + case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: + switch (def->targetType) { + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD: + VIR_FREE(def->target.addr); + break; + + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO: + VIR_FREE(def->target.name); + break; + } break; - case VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO: - VIR_FREE(def->target.name); + default: break; } @@ -2363,6 +2373,179 @@ error: goto cleanup; } +static int +virDomainChrDefaultTargetType(int devtype) { + + int target = -1; + + switch (devtype) { + case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: + virDomainReportError(VIR_ERR_XML_ERROR, + _("target type must be specified for %s device"), + virDomainChrDeviceTypeToString(devtype)); + break; + + case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE: + case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL: + case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL: + default: + /* No target type yet*/ + target = 0; + break; + } + + return target; +} + +static int +virDomainChrTargetTypeFromString(int devtype, + const char *targetType) +{ + int ret = -1; + int target = 0; + + if (!targetType) { + target = virDomainChrDefaultTargetType(devtype); + goto out; + } + + switch (devtype) { + case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: + target = virDomainChrChannelTargetTypeFromString(targetType); + break; + + case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL: + case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL: + default: + /* No target type yet*/ + target = 0; + break; + } + +out: + ret = target; + return ret; +} + +static const char * +virDomainChrTargetTypeToString(int deviceType, + int targetType) +{ + const char *type = NULL; + + switch (deviceType) { + case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: + type = virDomainChrChannelTargetTypeToString(targetType); + break; + default: + break; + } + + return type; +} + +static int +virDomainChrDefParseTargetXML(virDomainChrDefPtr def, + xmlNodePtr cur, + int flags ATTRIBUTE_UNUSED) +{ + int ret = -1; + unsigned int port; + const char *targetType = virXMLPropString(cur, "type"); + const char *addrStr = NULL; + const char *portStr = NULL; + + if ((def->targetType = + virDomainChrTargetTypeFromString(def->deviceType, targetType)) < 0) { + goto error; + } + + switch (def->deviceType) { + case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: + switch (def->targetType) { + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD: + addrStr = virXMLPropString(cur, "address"); + portStr = virXMLPropString(cur, "port"); + + if (addrStr == NULL) { + virDomainReportError(VIR_ERR_XML_ERROR, "%s", + _("guestfwd channel does not " + "define a target address")); + goto error; + } + + if (VIR_ALLOC(def->target.addr) < 0) { + virReportOOMError(); + goto error; + } + + if (virSocketParseAddr(addrStr, def->target.addr, 0) < 0) { + virDomainReportError(VIR_ERR_XML_ERROR, + _("%s is not a valid address"), + addrStr); + goto error; + } + + if (def->target.addr->stor.ss_family != AF_INET) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("guestfwd channel only supports " + "IPv4 addresses")); + goto error; + } + + if (portStr == NULL) { + virDomainReportError(VIR_ERR_XML_ERROR, "%s", + _("guestfwd channel does " + "not define a target port")); + goto error; + } + + if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) { + virDomainReportError(VIR_ERR_XML_ERROR, + _("Invalid port number: %s"), + portStr); + goto error; + } + + virSocketSetPort(def->target.addr, port); + break; + + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO: + def->target.name = virXMLPropString(cur, "name"); + break; + } + break; + + case VIR_DOMAIN_CHR_DEVICE_TYPE_MONITOR: + /* Nothing to parse */ + break; + + default: + portStr = virXMLPropString(cur, "port"); + if (portStr == NULL) { + /* Not required. It will be assigned automatically later */ + break; + } + + if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) { + virDomainReportError(VIR_ERR_XML_ERROR, + _("Invalid port number: %s"), + portStr); + goto error; + } + break; + } + + + ret = 0; +error: + VIR_FREE(targetType); + VIR_FREE(addrStr); + VIR_FREE(portStr); + + return ret; +} + /* Parse the XML definition for a character device * @param node XML nodeset to parse for net definition @@ -2415,9 +2598,6 @@ virDomainChrDefParseXML(xmlNodePtr node, char *mode = NULL; char *protocol = NULL; const char *nodeName; - const char *deviceType = NULL; - const char *addrStr = NULL; - const char *portStr = NULL; virDomainChrDefPtr def; if (VIR_ALLOC(def) < 0) { @@ -2433,15 +2613,9 @@ virDomainChrDefParseXML(xmlNodePtr node, nodeName = (const char *) node->name; if ((def->deviceType = virDomainChrDeviceTypeFromString(nodeName)) < 0) { - /* channel is handled below */ - if (STRNEQ(nodeName, "channel")) { - virDomainReportError(VIR_ERR_XML_ERROR, - _("unknown target type for character device: %s"), - nodeName); - VIR_FREE(def); - return NULL; - } - def->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_NULL; + virDomainReportError(VIR_ERR_XML_ERROR, + _("unknown character device type: %s"), + nodeName); } cur = node->children; @@ -2490,98 +2664,8 @@ virDomainChrDefParseXML(xmlNodePtr node, if (protocol == NULL) protocol = virXMLPropString(cur, "type"); } else if (xmlStrEqual(cur->name, BAD_CAST "target")) { - /* If target type isn't set yet, expect it to be set here */ - if (def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_NULL) { - deviceType = virXMLPropString(cur, "type"); - if (deviceType == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", - _("character device target does " - "not define a type")); - goto error; - } - if ((def->deviceType = - virDomainChrDeviceTypeFromString(deviceType)) < 0) - { - virDomainReportError(VIR_ERR_XML_ERROR, - _("unknown target type for " - "character device: %s"), - deviceType); - goto error; - } - } - - unsigned int port; - switch (def->deviceType) { - case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL: - case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL: - case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE: - portStr = virXMLPropString(cur, "port"); - if (portStr == NULL) { - /* Not required. It will be assigned automatically - * later */ - break; - } - - if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) { - virDomainReportError(VIR_ERR_XML_ERROR, - _("Invalid port number: %s"), - portStr); - goto error; - } - break; - - case VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD: - addrStr = virXMLPropString(cur, "address"); - portStr = virXMLPropString(cur, "port"); - - if (addrStr == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", - _("guestfwd channel does not " - "define a target address")); - goto error; - } - if (VIR_ALLOC(def->target.addr) < 0) { - virReportOOMError(); - goto error; - } - if (virSocketParseAddr(addrStr, def->target.addr, 0) < 0) - { - virDomainReportError(VIR_ERR_XML_ERROR, - _("%s is not a valid address"), - addrStr); - goto error; - } - - if (def->target.addr->stor.ss_family != AF_INET) { - virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, - "%s", _("guestfwd channel only supports " - "IPv4 addresses")); - goto error; - } - - if (portStr == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", - _("guestfwd channel does " - "not define a target port")); - goto error; - } - if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) { - virDomainReportError(VIR_ERR_XML_ERROR, - _("Invalid port number: %s"), - portStr); - goto error; - } - virSocketSetPort(def->target.addr, port); - break; - - case VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO: - def->target.name = virXMLPropString(cur, "name"); - break; - - default: - virDomainReportError(VIR_ERR_XML_ERROR, - _("unexpected target type type %u"), - def->deviceType); + if (virDomainChrDefParseTargetXML(def, cur, flags) < 0) { + goto error; } } } @@ -2714,9 +2798,6 @@ cleanup: VIR_FREE(connectHost); VIR_FREE(connectService); VIR_FREE(path); - VIR_FREE(deviceType); - VIR_FREE(addrStr); - VIR_FREE(portStr); return def; @@ -4496,7 +4577,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, def->channels[def->nchannels++] = chr; - if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO && + if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL && + chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO && chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) chr->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL; @@ -5011,7 +5093,7 @@ static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def) for (i = 0 ; i < def->nchannels ; i++) { virDomainChrDefPtr channel = def->channels[i]; - if (channel->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO) { + if (channel->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) { int idx = 0; if (channel->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL) idx = channel->info.addr.vioserial.controller; @@ -5593,28 +5675,25 @@ virDomainChrDefFormat(virBufferPtr buf, int flags) { const char *type = virDomainChrTypeToString(def->type); - const char *targetName = virDomainChrDeviceTypeToString(def->deviceType); - const char *elementName; + const char *elementName = virDomainChrDeviceTypeToString(def->deviceType); + const char *targetType = virDomainChrTargetTypeToString(def->deviceType, + def->targetType); int ret = 0; - switch (def->deviceType) { - /* channel types are in a common channel element */ - case VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD: - case VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO: - elementName = "channel"; - break; - - default: - elementName = targetName; - } - if (!type) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected char type %d"), def->type); return -1; } + if (!elementName) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected char device type %d"), + def->deviceType); + return -1; + } + /* Compat with legacy <console tty='/dev/pts/5'/> syntax */ virBufferVSprintf(buf, " <%s type='%s'", elementName, type); @@ -5693,47 +5772,57 @@ virDomainChrDefFormat(virBufferPtr buf, break; } + /* Format <target> block */ switch (def->deviceType) { - case VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD: - { + case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: { + if (!targetType) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not format channel target type")); + return -1; + } + virBufferVSprintf(buf, " <target type='%s'", targetType); + + switch (def->targetType) { + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD: { int port = virSocketGetPort(def->target.addr); if (port < 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to format guestfwd port")); return -1; } + const char *addr = virSocketFormatAddr(def->target.addr); if (addr == NULL) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to format guestfwd address")); return -1; } - virBufferVSprintf(buf, - " <target type='guestfwd' address='%s' port='%d'/>\n", + + virBufferVSprintf(buf, " address='%s' port='%d'", addr, port); VIR_FREE(addr); break; } - case VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO: - virBufferAddLit(buf, " <target type='virtio'"); - if (def->target.name) { - virBufferEscapeString(buf, " name='%s'", def->target.name); + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO: { + if (def->target.name) { + virBufferEscapeString(buf, " name='%s'", def->target.name); + } + break; + } + } virBufferAddLit(buf, "/>\n"); break; + } - case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL: - case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL: - case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE: - virBufferVSprintf(buf, " <target port='%d'/>\n", def->target.port); + case VIR_DOMAIN_CHR_DEVICE_TYPE_MONITOR: + /* Nothing to format */ break; default: - virDomainReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected character destination type %d"), - def->deviceType); - return -1; + virBufferVSprintf(buf, " <target port='%d'/>\n", def->target.port); + break; } if (virDomainDeviceInfoIsSet(&def->info)) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 86cc02a..966607f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -314,15 +314,20 @@ struct _virDomainNetDef { }; enum virDomainChrDeviceType { - VIR_DOMAIN_CHR_DEVICE_TYPE_NULL = 0, - VIR_DOMAIN_CHR_DEVICE_TYPE_MONITOR, + VIR_DOMAIN_CHR_DEVICE_TYPE_MONITOR = 0, VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL, VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL, VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE, - VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD, - VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO, + VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL, - VIR_DOMAIN_CHR_DEVICE_TYPE_LAST + VIR_DOMAIN_CHR_DEVICE_TYPE_LAST, +}; + +enum virDomainChrChannelTargetType { + VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD = 0, + VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO, + + VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST, }; enum virDomainChrType { @@ -351,6 +356,7 @@ typedef struct _virDomainChrDef virDomainChrDef; typedef virDomainChrDef *virDomainChrDefPtr; struct _virDomainChrDef { int deviceType; + int targetType; union { int port; /* parallel, serial, console */ virSocketAddrPtr addr; /* guestfwd */ @@ -1130,6 +1136,7 @@ VIR_ENUM_DECL(virDomainControllerModel) VIR_ENUM_DECL(virDomainFS) VIR_ENUM_DECL(virDomainNet) VIR_ENUM_DECL(virDomainChrDevice) +VIR_ENUM_DECL(virDomainChrChannelTarget) VIR_ENUM_DECL(virDomainChr) VIR_ENUM_DECL(virDomainSoundModel) VIR_ENUM_DECL(virDomainMemballoonModel) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index bcca274..8873e40 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -4477,8 +4477,8 @@ int qemudBuildCommandLine(virConnectPtr conn, virDomainChrDefPtr channel = def->channels[i]; char *devstr; - switch(channel->deviceType) { - case VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD: + switch(channel->targetType) { + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD: if (!(qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) || !(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) { qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -4504,7 +4504,7 @@ int qemudBuildCommandLine(virConnectPtr conn, ADD_ARG(devstr); break; - case VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO: + case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO: if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) { qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("virtio channel requires QEMU to support -device")); -- 1.7.1.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list