[libvirt] [PATCHv3 07/11] qemu: Allow multiple vhost-net openings

Michal Privoznik mprivozn at redhat.com
Thu May 16 12:49:36 UTC 2013


With multiqueue network feature, we are advised to pass multiple
vhost-net FDs as well. The ratio should be 1:1. Therefore we must
alter the qemuOpenVhostNet function to allow that.
---
 src/qemu/qemu_command.c | 60 ++++++++++++++++++++++++++++++++++++-------------
 src/qemu/qemu_command.h |  3 ++-
 src/qemu/qemu_hotplug.c | 12 ++++++----
 3 files changed, 54 insertions(+), 21 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index a053d49..ec66a33 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -405,17 +405,34 @@ cleanup:
 }
 
 
+/**
+ * qemuOpenVhostNet:
+ * @def: domain definition
+ * @net: network definition
+ * @qemuCaps: qemu binary capabilities
+ * @vhostfd: array of opened vhost-net device
+ * @vhostfdSize: size of @vhostfd array
+ *
+ * Open vhost-net, multiple times - if requested.
+ * In case, no vhost-net is needed, @vhostfdSize is set to 0
+ * and 0 is returned.
+ *
+ * Returns: 0 on success
+ *         -1 on failure
+ */
 int
 qemuOpenVhostNet(virDomainDefPtr def,
                  virDomainNetDefPtr net,
                  virQEMUCapsPtr qemuCaps,
-                 int *vhostfd)
+                 int *vhostfd,
+                 int *vhostfdSize)
 {
-    *vhostfd = -1;   /* assume we won't use vhost */
+    int i;
 
     /* If the config says explicitly to not use vhost, return now */
     if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_QEMU) {
-       return 0;
+        *vhostfdSize = 0;
+        return 0;
     }
 
     /* If qemu doesn't support vhost-net mode (including the -netdev command
@@ -430,6 +447,7 @@ qemuOpenVhostNet(virDomainDefPtr def,
                                    "this QEMU binary"));
             return -1;
         }
+        *vhostfdSize = 0;
         return 0;
     }
 
@@ -441,23 +459,32 @@ qemuOpenVhostNet(virDomainDefPtr def,
                                    "virtio network interfaces"));
             return -1;
         }
+        *vhostfdSize = 0;
         return 0;
     }
 
-    *vhostfd = open("/dev/vhost-net", O_RDWR);
-    virDomainAuditNetDevice(def, net, "/dev/vhost-net", *vhostfd >= 0);
+    for (i = 0; i < *vhostfdSize; i++) {
+        vhostfd[i] = open("/dev/vhost-net", O_RDWR);
+        virDomainAuditNetDevice(def, net, "/dev/vhost-net", vhostfd[i] >= 0);
 
-    /* If the config says explicitly to use vhost and we couldn't open it,
-     * report an error.
-     */
-    if ((*vhostfd < 0) &&
-        (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST)) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       "%s", _("vhost-net was requested for an interface, "
-                               "but is unavailable"));
-        return -1;
+        /* If the config says explicitly to use vhost and we couldn't open it,
+         * report an error.
+         */
+        if (vhostfd[i] < 0 &&
+            net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           "%s", _("vhost-net was requested for an interface, "
+                                   "but is unavailable"));
+            goto error;
+        }
     }
     return 0;
+
+error:
+    while (i--)
+        VIR_FORCE_CLOSE(vhostfd[i]);
+
+    return -1;
 }
 
 int
@@ -6477,10 +6504,11 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
         /* Attempt to use vhost-net mode for these types of
            network device */
         int vhostfd;
+        int vhostfdSize = 1;
 
-        if (qemuOpenVhostNet(def, net, qemuCaps, &vhostfd) < 0)
+        if (qemuOpenVhostNet(def, net, qemuCaps, &vhostfd, &vhostfdSize) < 0)
             goto cleanup;
-        if (vhostfd >= 0) {
+        if (vhostfdSize > 0) {
             virCommandTransferFD(cmd, vhostfd);
             if (virAsprintf(&vhostfdName, "%d", vhostfd) < 0) {
                 virReportOOMError();
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 6765c3a..c87b754 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -170,7 +170,8 @@ int qemuPhysIfaceConnect(virDomainDefPtr def,
 int qemuOpenVhostNet(virDomainDefPtr def,
                      virDomainNetDefPtr net,
                      virQEMUCapsPtr qemuCaps,
-                     int *vhostfd);
+                     int *vhostfd,
+                     int *vhostfdSize);
 
 int qemuNetworkPrepareDevices(virDomainDefPtr def);
 
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 0a1845a..fdc4b24 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -689,6 +689,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
     int tapfd = -1;
     char *vhostfd_name = NULL;
     int vhostfd = -1;
+    int vhostfdSize = 0;
     char *nicstr = NULL;
     char *netstr = NULL;
     virNetDevVPortProfilePtr vport = NULL;
@@ -738,7 +739,8 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
                                              priv->qemuCaps)) < 0)
             goto cleanup;
         iface_connected = true;
-        if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0)
+        vhostfdSize = 1;
+        if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd, &vhostfdSize) < 0)
             goto cleanup;
     } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
         if ((tapfd = qemuPhysIfaceConnect(vm->def, driver, net,
@@ -746,10 +748,12 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
                                           VIR_NETDEV_VPORT_PROFILE_OP_CREATE)) < 0)
             goto cleanup;
         iface_connected = true;
-        if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0)
+        vhostfdSize = 1;
+        if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd, &vhostfdSize) < 0)
             goto cleanup;
     } else if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
-        if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0)
+        vhostfdSize = 1;
+        if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd, &vhostfdSize) < 0)
             goto cleanup;
     }
 
@@ -792,7 +796,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
             goto no_memory;
     }
 
-    if (vhostfd != -1) {
+    if (vhostfdSize > 0) {
         if (virAsprintf(&vhostfd_name, "vhostfd-%s", net->info.alias) < 0)
             goto no_memory;
     }
-- 
1.8.2.1




More information about the libvir-list mailing list