]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
Support vhost-net mode at qemu startup for virtio network devices
authorLaine Stump <laine@laine.org>
Fri, 19 Mar 2010 15:58:14 +0000 (16:58 +0100)
committerDaniel Veillard <veillard@redhat.com>
Fri, 19 Mar 2010 15:58:14 +0000 (16:58 +0100)
Attempt to turn on vhost-net mode for devices of type NETWORK, BRIDGE,
and DIRECT (macvtap).

* src/qemu/qemu_conf.h: add vhostfd to qemuBuildHostNetStr prototype
  add qemudOpenVhostNet prototype new flag to set when :,vhost=" found in
  qemu help
* src/qemu/qemu_conf.c: * set QEMUD_CMD_FLAG_VNET_HOST is ",vhost=" found
  in qemu help
   - qemudOpenVhostNet - opens /dev/vhost-net to pass to qemu if everything
     is in place to use it.
   - qemuBuildHostNetStr - add vhostfd to commandline if it's not empty
     (higher levels decide whether or not to fill it in)
   - qemudBuildCommandLine - if /dev/vhost-net is successfully opened, add
     its fd to tapfds array so it isn't closed on qemu exec, and populate
     vhostfd_name to be passed in to commandline builder.
* src/qemu/qemu_driver.c: add filler 0 for new arg to qemuBuildHostNetStr,
  along with a note that this must be implemented in order for hot-plug of
  vhost-net virtio devices to work properly (once qemu "netdev_add" monitor
  command is implemented).

src/qemu/qemu_conf.c
src/qemu/qemu_conf.h
src/qemu/qemu_driver.c

index fb23c529de80b98a71018e5f5eab3a25902f9993..f2d36f71c0e039abc2759c57154795f772d04891 100644 (file)
@@ -1183,6 +1183,10 @@ static unsigned long long qemudComputeCmdFlags(const char *help,
     if (is_kvm && (version >= 10000 || kvm_version >= 74))
         flags |= QEMUD_CMD_FLAG_VNET_HDR;
 
+    if (is_kvm && strstr(help, ",vhost=")) {
+        flags |= QEMUD_CMD_FLAG_VNET_HOST;
+    }
+
     /*
      * Handling of -incoming arg with varying features
      *  -incoming tcp    (kvm >= 79, qemu >= 0.10.0)
@@ -1597,6 +1601,27 @@ cleanup:
 }
 
 
+int
+qemudOpenVhostNet(virDomainNetDefPtr net,
+                  unsigned long long qemuCmdFlags)
+{
+
+    /* If qemu supports vhost-net mode (including the -netdev command
+     * option), the nic model is virtio, and we can open
+     * /dev/vhost_net, assume that vhost-net mode is available and
+     * return the fd to /dev/vhost_net. Otherwise, return -1.
+     */
+
+    if (!(qemuCmdFlags & QEMUD_CMD_FLAG_VNET_HOST &&
+          qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV &&
+          qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE &&
+          net->model && STREQ(net->model, "virtio")))
+        return -1;
+
+    return open("/dev/vhost-net", O_RDWR, 0);
+}
+
+
 static int qemuDomainDeviceAliasIndex(virDomainDeviceInfoPtr info,
                                       const char *prefix)
 {
@@ -2611,7 +2636,8 @@ char *
 qemuBuildHostNetStr(virDomainNetDefPtr net,
                     char type_sep,
                     int vlan,
-                    const char *tapfd)
+                    const char *tapfd,
+                    const char *vhostfd)
 {
     virBuffer buf = VIR_BUFFER_INITIALIZER;
 
@@ -2680,6 +2706,10 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
                           type_sep, net->info.alias);
     }
 
+    if (vhostfd && *vhostfd) {
+        virBufferVSprintf(&buf, ",vhost=on,vhostfd=%s", vhostfd);
+    }
+
     if (virBufferError(&buf)) {
         virBufferFreeAndReset(&buf);
         virReportOOMError();
@@ -3828,6 +3858,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
             virDomainNetDefPtr net = def->nets[i];
             char *nic, *host;
             char tapfd_name[50];
+            char vhostfd_name[50] = "";
             int vlan;
 
             /* VLANs are not used with -netdev, so don't record them */
@@ -3871,6 +3902,24 @@ int qemudBuildCommandLine(virConnectPtr conn,
                     goto no_memory;
             }
 
+            if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
+                net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+                net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+                /* Attempt to use vhost-net mode for these types of
+                   network device */
+                int vhostfd = qemudOpenVhostNet(net, qemuCmdFlags);
+                if (vhostfd >= 0) {
+                    if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0) {
+                        close(vhostfd);
+                        goto no_memory;
+                    }
+
+                    (*tapfds)[(*ntapfds)++] = vhostfd;
+                    if (snprintf(vhostfd_name, sizeof(vhostfd_name), "%d", vhostfd)
+                        >= sizeof(vhostfd_name))
+                        goto no_memory;
+                }
+            }
             /* Possible combinations:
              *
              *  1. Old way:   -net nic,model=e1000,vlan=1 -net tap,vlan=1
@@ -3882,8 +3931,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
             if ((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
                 (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
                 ADD_ARG_LIT("-netdev");
-                if (!(host = qemuBuildHostNetStr(net, ',',
-                                                 vlan, tapfd_name)))
+                if (!(host = qemuBuildHostNetStr(net, ',', vlan,
+                                                 tapfd_name, vhostfd_name)))
                     goto error;
                 ADD_ARG(host);
             }
@@ -3901,8 +3950,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
             if (!((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
                   (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))) {
                 ADD_ARG_LIT("-net");
-                if (!(host = qemuBuildHostNetStr(net, ',',
-                                                 vlan, tapfd_name)))
+                if (!(host = qemuBuildHostNetStr(net, ',', vlan,
+                                                 tapfd_name, vhostfd_name)))
                     goto error;
                 ADD_ARG(host);
             }
index 6a9de5e55c812d5172498fbdca217a22fc523321..2d62cc409ebacd504da038664705c7ae9610c9fb 100644 (file)
@@ -83,6 +83,7 @@ enum qemud_cmd_flags {
     QEMUD_CMD_FLAG_SMP_TOPOLOGY  = (1 << 28), /* Is sockets=s,cores=c,threads=t available for -smp? */
     QEMUD_CMD_FLAG_NETDEV        = (1 << 29), /* The -netdev flag & netdev_add/remove monitor commands */
     QEMUD_CMD_FLAG_RTC           = (1 << 30), /* The -rtc flag for clock options */
+    QEMUD_CMD_FLAG_VNET_HOST     = (1 << 31), /* vnet-host support is available in qemu */
 };
 
 /* Main driver state */
@@ -200,7 +201,8 @@ int         qemudBuildCommandLine       (virConnectPtr conn,
 char * qemuBuildHostNetStr(virDomainNetDefPtr net,
                            char type_sep,
                            int vlan,
-                           const char *tapfd);
+                           const char *tapfd,
+                           const char *vhostfd);
 
 /* Legacy, pre device support */
 char * qemuBuildNicStr(virDomainNetDefPtr net,
@@ -252,6 +254,10 @@ int         qemudNetworkIfaceConnect    (virConnectPtr conn,
                                          unsigned long long qemuCmdFlags)
     ATTRIBUTE_NONNULL(1);
 
+int
+qemudOpenVhostNet(virDomainNetDefPtr net,
+                  unsigned long long qemuCmdFlags);
+
 int qemudPhysIfaceConnect(virConnectPtr conn,
                           struct qemud_driver *driver,
                           virDomainNetDefPtr net,
index a3aae33c8ba14539f1229347a77b0988d4b89007..3e8e76ec53560d59a8c0c9c8e107d1b7572916f8 100644 (file)
@@ -6373,8 +6373,9 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
         qemuDomainObjExitMonitorWithDriver(driver, vm);
     }
 
+    /* FIXME - need to support vhost-net here (5th arg) */
     if (!(netstr = qemuBuildHostNetStr(net, ' ',
-                                       vlan, tapfd_name)))
+                                       vlan, tapfd_name, 0)))
         goto try_tapfd_close;
 
     qemuDomainObjEnterMonitorWithDriver(driver, vm);