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

Re: [libvirt] [PATCH] Add XML config switch to enable/disable vhost-net support

On 01/14/2011 08:22 AM, Daniel P. Berrange wrote:
On Thu, Jan 13, 2011 at 01:45:28AM -0500, Laine Stump wrote:
This patch is in response to


The existing libvirt support for the vhost-net backend to the virtio
network driver happens automatically - if the vhost-net device is
available, it is always enabled, otherwise the standard userland
virtio backend is used.

This patch makes it possible to force whether or not vhost-net is used
with a bit of XML. Adding a<driver>  element to the interface XML, eg:

      <interface type="network">
        <model type="virtio"/>
        <driver name="vhost"/>

will force use of vhost-net (if it's not available, the domain will
fail to start). if driver name="qemu", vhost-net will not be used even
if it is available.

If there is no<driver name='xxx'/>  in the config, libvirt will revert
to the pre-existing automatic behavior - use vhost-net if it's
available, and userland backend if vhost-net isn't available.

Note that I don't really like the "name='vhost|qemu'" nomenclature,
but am including it here just to get the patches on the list. I could
live with it this way, or with any of the following (anyone have a
strong opinion?) (note that in all cases, nothing specified means "try
to use vhost, but fallback to userland if necessary")

I wanted 'name=' becasue that matches<driver>  usage in<disk>.
This rules out the first options completely, since we can just
play with attribute values. kernel|user is nice, except when
QEMU invent  vhost2, and now 'kernel' is no longer unique :-(
Also we used 'name=qemu' already in<disk>  to refer to the
in-QEMU disk backend, and there's likely to be a 'vhost' backend
for disks too in the future. So in summary I think 'name=vhost|qemu'
is the best optionl.

Okay, I'm convinced! :-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b4df38c..04ed502 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -184,6 +184,10 @@ VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,

+              "qemu",
+              "vhost")
@@ -2289,6 +2293,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
      char *address = NULL;
      char *port = NULL;
      char *model = NULL;
+    char *backend = NULL;
      char *filter = NULL;
      char *internal = NULL;
      char *devaddr = NULL;
@@ -2371,6 +2376,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
                  script = virXMLPropString(cur, "path");
              } else if (xmlStrEqual (cur->name, BAD_CAST "model")) {
                  model = virXMLPropString(cur, "type");
+            } else if (xmlStrEqual (cur->name, BAD_CAST "driver")) {
+                backend = virXMLPropString(cur, "name");
              } else if (xmlStrEqual (cur->name, BAD_CAST "filterref")) {
                  filter = virXMLPropString(cur, "filter");
@@ -2558,6 +2565,18 @@ virDomainNetDefParseXML(virCapsPtr caps,
          model = NULL;

+    if ((backend != NULL)&&
+        (def->model&&  STREQ(def->model, "virtio"))) {
+        int b;
+        if ((b = virDomainNetBackendTypeFromString(backend))<  0) {
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                 _("Unkown interface<driver name='%s'>  has been specified"),
+                                 backend);
+            goto error;
+        }
+        def->backend = b;
+        def->backend_specified = 1;
+    }
      if (filter != NULL) {
          switch (def->type) {
@@ -2584,6 +2603,7 @@ cleanup:
+    VIR_FREE(backend);
@@ -6275,9 +6295,14 @@ virDomainNetDefFormat(virBufferPtr buf,
      if (def->ifname)
          virBufferEscapeString(buf, "<target dev='%s'/>\n",
-    if (def->model)
+    if (def->model) {
          virBufferEscapeString(buf, "<model type='%s'/>\n",
+        if (STREQ(def->model, "virtio")&&  def->backend_specified) {
+            virBufferVSprintf(buf, "<driver name='%s'/>\n",
+                              virDomainNetBackendTypeToString(def->backend));
+        }
+    }
      if (def->filter) {
          virBufferEscapeString(buf, "<filterref filter='%s'",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a459a22..451ccad 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -292,6 +292,13 @@ enum virDomainNetType {

+/* the backend driver used for virtio interfaces */
+enum virDomainNetBackendType {
+    VIR_DOMAIN_NET_BACKEND_TYPE_QEMU,         /* userland */
+    VIR_DOMAIN_NET_BACKEND_TYPE_VHOST,        /* kernel */

  /* the mode type for macvtap devices */
  enum virDomainNetdevMacvtapType {
@@ -310,6 +317,8 @@ struct _virDomainNetDef {
      enum virDomainNetType type;
      unsigned char mac[VIR_MAC_BUFLEN];
      char *model;
+    enum virDomainNetBackendType backend;
+    int backend_specified : 1;
I don't really like this pattern since it is at odds with the way
we handle defaults elsewhere which is to include the default as
the first enum value, eg

   enum virDomainNetBackendType {
     VIR_DOMAIN_NET_BACKEND_TYPE_DEFAULT,      /* Try best available */
     VIR_DOMAIN_NET_BACKEND_TYPE_QEMU,         /* userland */
     VIR_DOMAIN_NET_BACKEND_TYPE_VHOST,        /* kernel */


And then we do

   if (def->backend)
      ...print XML...

when formatting the XML, so that the 'name=default' never
actually appears in the XML output.

Right. What I didn't like was that, using the VIR_ENUM_IMPL() macro, we would end up giving the user the ability to put <driver name='default'/> into the XML, which would then disappear. In his review, Eric pointed out the elegant solution of simply generating an error during parse if they try to enter that value; everything else will already do what we want. So that's what I'm doing in V2.

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