[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 2/3] Add domain support for virtio channel



Add support for virtio-serial by defining a new 'virtio' channel target type and
a virtio-serial controller. Allows the following to be specified in a domain:

<controller type='virtio-serial' index='0'/>
<channel type='pty'>
  <target type='virtio' name='org.linux-kvm.port.0'/>
</channel>

* docs/schemas/domain.rng: Add virtio-serial controller and virtio channel type.
* src/conf/domain_conf.[ch]: Domain parsing/serialization for virtio-serial
                             controller and virtio channel.
* tests/qemuxml2xmltest.c
  tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml
                           : add domain xml parsing test
* src/libvirt_private.syms
  src/qemu/qemu_conf.c: virDomainDefAddDiskControllers() renamed to
                        virDomainDefAddImplicitControllers()
---
 docs/schemas/domain.rng                            |   25 ++++-
 src/conf/domain_conf.c                             |  124 +++++++++++++++++---
 src/conf/domain_conf.h                             |   10 ++-
 src/libvirt_private.syms                           |    2 +-
 src/qemu/qemu_conf.c                               |    2 +-
 .../qemuxml2argv-channel-virtio.xml                |   28 +++++
 tests/qemuxml2xmltest.c                            |    1 +
 7 files changed, 173 insertions(+), 19 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml

diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 827ff6f..a3247b9 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -530,6 +530,7 @@
             <value>ide</value>
             <value>scsi</value>
             <value>sata</value>
+            <value>virtio-serial</value>
           </choice>
         </attribute>
       </optional>
@@ -1120,12 +1121,34 @@
       <attribute name="port"/>
     </element>
   </define>
+  <define name="virtioTarget">
+    <element name="target">
+      <attribute name="type">
+          <value>virtio</value>
+      </attribute>
+      <optional>
+        <attribute name="name"/>
+      </optional>
+      <optional>
+        <attribute name="bytelimit"/>
+      </optional>
+      <optional>
+        <attribute name="guestbytelimit"/>
+      </optional>
+      <optional>
+        <attribute name="cachebuffers"/>
+      </optional>
+    </element>
+  </define>
   <define name="channel">
     <element name="channel">
       <ref name="qemucdevSrcType"/>
       <interleave>
         <ref name="qemucdevSrcDef"/>
-        <ref name="guestfwdTarget"/>
+        <choice>
+          <ref name="guestfwdTarget"/>
+          <ref name="virtioTarget"/>
+        </choice>
 	<optional>
 	  <ref name="address"/>
 	</optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e548d1d..3b96086 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -124,7 +124,8 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
               "ide",
               "fdc",
               "scsi",
-              "sata")
+              "sata",
+              "virtio-serial")
 
 VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST,
               "mount",
@@ -148,7 +149,8 @@ VIR_ENUM_IMPL(virDomainChrTarget, VIR_DOMAIN_CHR_TARGET_TYPE_LAST,
               "parallel",
               "serial",
               "console",
-              "guestfwd")
+              "guestfwd",
+              "virtio")
 
 VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST,
               "null",
@@ -449,6 +451,13 @@ void virDomainChrDefFree(virDomainChrDefPtr def)
     case VIR_DOMAIN_CHR_TARGET_TYPE_GUESTFWD:
         VIR_FREE(def->target.addr);
         break;
+
+    case VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO:
+        VIR_FREE(def->target.virtio.name);
+        VIR_FREE(def->target.virtio.byteLimit);
+        VIR_FREE(def->target.virtio.guestByteLimit);
+        VIR_FREE(def->target.virtio.cacheBuffers);
+        break;
     }
 
     switch (def->type) {
@@ -1460,7 +1469,7 @@ virDomainControllerDefParseXML(virConnectPtr conn,
 
     type = virXMLPropString(node, "type");
     if (type) {
-        if ((def->type = virDomainDiskBusTypeFromString(type)) < 0) {
+        if ((def->type = virDomainControllerTypeFromString(type)) < 0) {
             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
                                  _("unknown disk controller type '%s'"), type);
             goto error;
@@ -2081,6 +2090,48 @@ virDomainChrDefParseXML(virConnectPtr conn,
                     virSocketSetPort(def->target.addr, port);
                     break;
 
+                case VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO:
+                    def->target.virtio.name
+                        = virXMLPropString(cur, "name");
+                    def->target.virtio.byteLimit
+                        = virXMLPropString(cur, "bytelimit");
+                    def->target.virtio.guestByteLimit
+                        = virXMLPropString(cur, "guestbytelimit");
+                    def->target.virtio.cacheBuffers
+                        = virXMLPropString(cur, "cachebuffers");
+
+                    /* Ensure bytelimit and guestbytelimit are positive integers
+                     * if they are defined */
+                    unsigned int testUI;
+                    if (def->target.virtio.byteLimit &&
+                       virStrToLong_ui(def->target.virtio.byteLimit,
+                                       NULL, 10, &testUI) < 0) {
+                        virDomainReportError(conn, VIR_ERR_XML_ERROR,
+                                             _("Invalid byte_limit: %s"),
+                                             def->target.virtio.byteLimit);
+                        goto error;
+                    }
+                    if (def->target.virtio.guestByteLimit &&
+                       virStrToLong_ui(def->target.virtio.guestByteLimit,
+                                       NULL, 10, &testUI) < 0) {
+                        virDomainReportError(conn, VIR_ERR_XML_ERROR,
+                                             _("Invalid guest_byte_limit: %s"),
+                                             def->target.virtio.guestByteLimit);
+                        goto error;
+                    }
+
+                    /* Ensure that cacheBuffers is either 0 or 1 if it defined
+                     */
+                    if (def->target.virtio.cacheBuffers &&
+                       STRNEQ(def->target.virtio.cacheBuffers, "0") &&
+                       STRNEQ(def->target.virtio.cacheBuffers, "1")) {
+                        virDomainReportError(conn, VIR_ERR_XML_ERROR,
+                                             _("Invalid cache_buffers: %s"),
+                                             def->target.virtio.cacheBuffers);
+                        goto error;
+                    }
+                    break;
+
                 default:
                     virDomainReportError(conn, VIR_ERR_XML_ERROR,
                                          _("unexpected target type type %u"),
@@ -3640,12 +3691,6 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
     }
     VIR_FREE(nodes);
 
-    /* Auto-add any further disk controllers implied by declared <disk>
-     * elements, but not present as <controller> elements
-     */
-    if (virDomainDefAddDiskControllers(def) < 0)
-        goto error;
-
     /* analysis of the filesystems */
     if ((n = virXPathNodeSet(conn, "./devices/filesystem", ctxt, &nodes)) < 0) {
         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
@@ -3970,6 +4015,11 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
             goto error;
     }
 
+    /* Auto-add any implied controllers which aren't present
+     */
+    if (virDomainDefAddImplicitControllers(def) < 0)
+        goto error;
+
     return def;
 
 no_memory:
@@ -4247,9 +4297,9 @@ cleanup:
     return obj;
 }
 
-static int virDomainDefMaybeAddDiskController(virDomainDefPtr def,
-                                              int type,
-                                              int idx)
+static int virDomainDefMaybeAddController(virDomainDefPtr def,
+                                          int type,
+                                          int idx)
 {
     int found = 0;
     int i;
@@ -4302,7 +4352,7 @@ static int virDomainDefAddDiskControllersForType(virDomainDefPtr def,
     }
 
     for (i = 0 ; i <= maxController ; i++) {
-        if (virDomainDefMaybeAddDiskController(def, controllerType, i) < 0)
+        if (virDomainDefMaybeAddController(def, controllerType, i) < 0)
             return -1;
     }
 
@@ -4310,13 +4360,33 @@ static int virDomainDefAddDiskControllersForType(virDomainDefPtr def,
 }
 
 
+static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def)
+{
+    /* Look for any virtio serial device */
+    int i;
+    for (i = 0 ; i < def->nchannels ; i++) {
+        virDomainChrDefPtr channel = def->channels[i];
+
+        if (channel->targetType == VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO) {
+            /* Try to add a virtio serial controller with index 0 */
+            if (virDomainDefMaybeAddController(def,
+                    VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, 0) < 0)
+                return -1;
+            break;
+        }
+    }
+
+    return 0;
+}
+
+
 /*
- * Based on the declared <address type=drive> info for any disks,
+ * Based on the declared <address/> info for any devices,
  * add neccessary drive controllers which are not already present
  * in the XML. This is for compat with existing apps which will
  * not know/care about <controller> info in the XML
  */
-int virDomainDefAddDiskControllers(virDomainDefPtr def)
+int virDomainDefAddImplicitControllers(virDomainDefPtr def)
 {
     if (virDomainDefAddDiskControllersForType(def,
                                               VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
@@ -4333,6 +4403,9 @@ int virDomainDefAddDiskControllers(virDomainDefPtr def)
                                               VIR_DOMAIN_DISK_BUS_IDE) < 0)
         return -1;
 
+    if (virDomainDefMaybeAddVirtioSerialController(def) < 0)
+        return -1;
+
     return 0;
 }
 
@@ -4837,6 +4910,7 @@ virDomainChrDefFormat(virConnectPtr conn,
     switch (def->targetType) {
     /* channel types are in a common channel element */
     case VIR_DOMAIN_CHR_TARGET_TYPE_GUESTFWD:
+    case VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO:
         elementName = "channel";
         break;
 
@@ -4950,6 +5024,26 @@ virDomainChrDefFormat(virConnectPtr conn,
             break;
         }
 
+    case VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO:
+        virBufferVSprintf(buf, "      <target type='virtio'");
+        if (def->target.virtio.name) {
+            virBufferVSprintf(buf, " name='%s'", def->target.virtio.name);
+        }
+        if (def->target.virtio.byteLimit) {
+            virBufferVSprintf(buf, " bytelimit='%s'",
+                              def->target.virtio.byteLimit);
+        }
+        if (def->target.virtio.guestByteLimit) {
+            virBufferVSprintf(buf, " guestbytelimit='%s'",
+                              def->target.virtio.guestByteLimit);
+        }
+        if (def->target.virtio.cacheBuffers) {
+            virBufferVSprintf(buf, " cachebuffers='%s'",
+                              def->target.virtio.cacheBuffers);
+        }
+        virBufferVSprintf(buf, "/>\n");
+        break;
+
     case VIR_DOMAIN_CHR_TARGET_TYPE_PARALLEL:
     case VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL:
     case VIR_DOMAIN_CHR_TARGET_TYPE_CONSOLE:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7be090d..da2115e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -166,6 +166,7 @@ enum virDomainControllerType {
     VIR_DOMAIN_CONTROLLER_TYPE_FDC,
     VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
     VIR_DOMAIN_CONTROLLER_TYPE_SATA,
+    VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL,
 
     VIR_DOMAIN_CONTROLLER_TYPE_LAST
 };
@@ -260,6 +261,7 @@ enum virDomainChrTargetType {
     VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL,
     VIR_DOMAIN_CHR_TARGET_TYPE_CONSOLE,
     VIR_DOMAIN_CHR_TARGET_TYPE_GUESTFWD,
+    VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO,
 
     VIR_DOMAIN_CHR_TARGET_TYPE_LAST
 };
@@ -293,6 +295,12 @@ struct _virDomainChrDef {
     union {
         int port; /* parallel, serial, console */
         virSocketAddrPtr addr; /* guestfwd */
+        struct {
+            char *name;
+            char *byteLimit;
+            char *guestByteLimit;
+            char *cacheBuffers;
+        } virtio; /* virtio */
     } target;
 
     int type;
@@ -782,7 +790,7 @@ virDomainObjPtr virDomainObjParseNode(virConnectPtr conn,
                                       xmlDocPtr xml,
                                       xmlNodePtr root);
 
-int virDomainDefAddDiskControllers(virDomainDefPtr def);
+int virDomainDefAddImplicitControllers(virDomainDefPtr def);
 
 #endif
 char *virDomainDefFormat(virConnectPtr conn,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d56fb7d..9dd1866 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -184,7 +184,7 @@ virDomainDeviceInfoIsSet;
 virDomainControllerTypeToString;
 virDomainControllerDefFree;
 virDomainDeviceAddressTypeToString;
-virDomainDefAddDiskControllers;
+virDomainDefAddImplicitControllers;
 virDomainDefClearPCIAddresses;
 virDomainDefClearDeviceAliases;
 
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 3b7793f..0c67334 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -5410,7 +5410,7 @@ virDomainDefPtr qemuParseCommandLine(virConnectPtr conn,
             goto no_memory;
     }
 
-    if (virDomainDefAddDiskControllers(def) < 0)
+    if (virDomainDefAddImplicitControllers(def) < 0)
         goto error;
 
     return def;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml
new file mode 100644
index 0000000..da5fa6c
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml
@@ -0,0 +1,28 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219200</memory>
+  <currentMemory>219200</currentMemory>
+  <vcpu cpuset='1-4,8-20,525'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <controller type='virtio-serial' index='0'/>
+    <channel type='pty'>
+      <target type='virtio' name='org.linux-kvm.port.0' bytelimit='1048576' guestbytelimit='1048576' cachebuffers='1'/>
+    </channel>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 0302696..7ea8e79 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -133,6 +133,7 @@ mymain(int argc, char **argv)
     DO_TEST("parallel-tcp");
     DO_TEST("console-compat");
     DO_TEST("channel-guestfwd");
+    DO_TEST("channel-virtio");
 
     DO_TEST("hostdev-usb-product");
     DO_TEST("hostdev-usb-address");
-- 
1.6.6


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]