[libvirt] [PATCH 1/4] vhost-user support: domain configuration

Michal Privoznik mprivozn at redhat.com
Thu Jul 10 16:01:50 UTC 2014


On 02.07.2014 15:20, Michele Paolino wrote:
> vhost-user is added as a virDomainChrSourceDefPtr variable in the
> virtual network interface configuration structure.
> This patch adds support to parse vhost-user element. The XML file
> looks like:
> 
> <interface type='vhostuser'>
>      <source type='unix' path='/tmp/vhost.sock' mode='server'/>
>      <mac address='52:54:00:3b:83:1a'/>
>      <model type='virtio'/>
> </interface>
> 
> Signed-off-by: Michele Paolino <m.paolino at virtualopensystems.com>
> ---
>   src/conf/domain_conf.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++
>   src/conf/domain_conf.h | 10 +++++--
>   2 files changed, 89 insertions(+), 2 deletions(-)

Introducing a new device (subtype of a device) must always go hand in hand with documentation and XML schema adjustment. Moreover, it would be nice to test the new XML (e.g. domainschematest or qemuxml2argv stub (a .xml file under tests/qemuxml2argvdata without .args counterpart which will be introduced once qemu implementation is done)).

> 
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index ea09bdc..de52ca4 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -349,6 +349,7 @@ VIR_ENUM_IMPL(virDomainFSWrpolicy, VIR_DOMAIN_FS_WRPOLICY_LAST,
>   VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
>                 "user",
>                 "ethernet",
> +              "vhostuser",
>                 "server",
>                 "client",
>                 "mcast",
> @@ -1361,6 +1362,10 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
>           VIR_FREE(def->data.ethernet.ipaddr);
>           break;
>   
> +    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
> +        virDomainChrSourceDefFree(def->data.vhostuser);
> +        break;
> +
>       case VIR_DOMAIN_NET_TYPE_SERVER:
>       case VIR_DOMAIN_NET_TYPE_CLIENT:
>       case VIR_DOMAIN_NET_TYPE_MCAST:
> @@ -6665,6 +6670,9 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
>       char *mode = NULL;
>       char *linkstate = NULL;
>       char *addrtype = NULL;
> +    char *vhostuser_mode = NULL;
> +    char *vhostuser_path = NULL;
> +    char *vhostuser_type = NULL;
>       virNWFilterHashTablePtr filterparams = NULL;
>       virDomainActualNetDefPtr actual = NULL;
>       xmlNodePtr oldnode = ctxt->node;
> @@ -6710,6 +6718,21 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
>                          xmlStrEqual(cur->name, BAD_CAST "source")) {
>                   dev  = virXMLPropString(cur, "dev");
>                   mode = virXMLPropString(cur, "mode");
> +            } else if (!vhostuser_path && !vhostuser_mode && !vhostuser_type
> +                       && def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER &&
> +                       xmlStrEqual(cur->name, BAD_CAST "source")) {
> +                vhostuser_type = virXMLPropString(cur, "type");
> +                if (!vhostuser_type || STREQ(vhostuser_type, "unix")) {
> +                    vhostuser_path = virXMLPropString(cur, "path");
> +                    vhostuser_mode = virXMLPropString(cur, "mode");
> +                }
> +                else {
> +                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                                   _("type='%s' unsupported for"
> +                                   " <interface type='vhostuser'>"),
> +                                   vhostuser_type);
> +                    goto error;

I'd move this check a few lines below to the other checks.

> +                }
>               } else if (!def->virtPortProfile
>                          && xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
>                   if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
> @@ -6867,6 +6890,50 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
>           actual = NULL;
>           break;
>   
> +    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
> +        if (!model || STRNEQ(model, "virtio")) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("Wrong or no <model> 'type' attribute "
> +                           "specified with <interface type='vhostuser'/>. "
> +                           "vhostuser requires the virtio-net* frontend"));
> +            goto error;
> +        }
> +
> +        if (VIR_ALLOC(def->data.vhostuser) < 0)
> +            goto error;
> +
> +        if (STREQ(vhostuser_type, "unix")) {

Ouch, in the code I've commented above, you allow vhostuser_type to be a NULL, so this needs to be STREQ_NULLABLE().

> +
> +            (def->data.vhostuser)->type = VIR_DOMAIN_CHR_TYPE_UNIX;

I haven't seen such braces usage since DV stopped writing patches :)

> +
> +            if (vhostuser_path == NULL) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                               _("No <source> 'path' attribute "
> +                               "specified with <interface "
> +                               "type='vhostuser'/>"));
> +                goto error;
> +            }
> +
> +            (def->data.vhostuser)->data.nix.path = vhostuser_path;
> +
> +            if (vhostuser_mode == NULL) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                               _("No <source> 'mode' attribute "
> +                               "specified with <interface "
> +                               "type='vhostuser'/>"));
> +                goto error;
> +            }
> +
> +            if (STREQ(vhostuser_mode, "server"))
> +                (def->data.vhostuser)->data.nix.listen = true;

Should we disallow other modes? What if user passes:

<interface type='vhostuser'>
  <source type='unix' path='/some/dummy/path' mode='blah'/>
</interface>



> +
> +        }
> +
> +        vhostuser_type = NULL;
> +        vhostuser_path = NULL;
> +        vhostuser_mode = NULL;

I don't think you want to set vhostuser_type or vhostuser_mode to NULL here. In case of _path it's okay as you are stealing the pointer into the CharDev struct, but the _type and _mode are not stolen anywhere so you're leaking them effectively.

> +        break;
> +
>       case VIR_DOMAIN_NET_TYPE_ETHERNET:
>           if (dev != NULL) {
>               def->data.ethernet.dev = dev;
> @@ -7112,6 +7179,9 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
>       VIR_FREE(portgroup);
>       VIR_FREE(address);
>       VIR_FREE(port);
> +    VIR_FREE(vhostuser_type);
> +    VIR_FREE(vhostuser_path);
> +    VIR_FREE(vhostuser_mode);
>       VIR_FREE(ifname);
>       VIR_FREE(dev);
>       virDomainActualNetDefFree(actual);
> @@ -15989,6 +16059,17 @@ virDomainNetDefFormat(virBufferPtr buf,
>                                     def->data.ethernet.ipaddr);
>               break;
>   
> +        case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
> +            if ((def->data.vhostuser)->type == VIR_DOMAIN_CHR_TYPE_UNIX) {
> +                virBufferAddLit(buf, "<source type='unix'");
> +                virBufferEscapeString(buf, " path='%s'",
> +                                      (def->data.vhostuser)->data.nix.path);
> +                if ((def->data.vhostuser)->data.nix.listen)
> +                    virBufferAddLit(buf, " mode='server'");
> +                virBufferAddLit(buf, "/>\n");
> +            }
> +            break;
> +
>           case VIR_DOMAIN_NET_TYPE_BRIDGE:
>               virBufferEscapeString(buf, "<source bridge='%s'/>\n",
>                                     def->data.bridge.brname);
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index eb5bad7..91f7524 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -133,6 +133,12 @@ typedef virDomainIdMapDef *virDomainIdMapDefPtr;
>   typedef struct _virDomainPanicDef virDomainPanicDef;
>   typedef virDomainPanicDef *virDomainPanicDefPtr;
>   
> +/* forward declarations virDomainChrSourceDef, required by
> + * virDomainNetDef
> + */
> +typedef struct _virDomainChrSourceDef virDomainChrSourceDef;
> +typedef virDomainChrSourceDef *virDomainChrSourceDefPtr;
> +
>   /* Flags for the 'type' field in virDomainDeviceDef */
>   typedef enum {
>       VIR_DOMAIN_DEVICE_NONE = 0,
> @@ -795,6 +801,7 @@ struct _virDomainFSDef {
>   typedef enum {
>       VIR_DOMAIN_NET_TYPE_USER,
>       VIR_DOMAIN_NET_TYPE_ETHERNET,
> +    VIR_DOMAIN_NET_TYPE_VHOSTUSER,
>       VIR_DOMAIN_NET_TYPE_SERVER,
>       VIR_DOMAIN_NET_TYPE_CLIENT,
>       VIR_DOMAIN_NET_TYPE_MCAST,

This change requires other modifications too. For instance I'm seeing this:

  CC       xenxs/libvirt_xenxs_la-xen_sxpr.lo
xenxs/xen_sxpr.c: In function 'xenFormatSxprNet':
xenxs/xen_sxpr.c:1889:5: error: enumeration value 'VIR_DOMAIN_NET_TYPE_VHOSTUSER' not handled in switch [-Werror=switch]
     switch (def->type) {
     ^
cc1: all warnings being treated as errors

and its repetitions in other drivers.

> @@ -880,6 +887,7 @@ struct _virDomainNetDef {
>               char *dev;
>               char *ipaddr;
>           } ethernet;
> +        virDomainChrSourceDefPtr vhostuser;
>           struct {
>               char *address;
>               int port;
> @@ -1006,8 +1014,6 @@ typedef enum {
>   } virDomainChrSpicevmcName;
>   
>   /* The host side information for a character device.  */
> -typedef struct _virDomainChrSourceDef virDomainChrSourceDef;
> -typedef virDomainChrSourceDef *virDomainChrSourceDefPtr;
>   struct _virDomainChrSourceDef {
>       int type; /* virDomainChrType */
>       union {
> 

I think this are the bits you need to squash in (don't forget the documentation on RNG schema):

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 4920a4e..1d64f68 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -6650,17 +6650,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
                        && def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER &&
                        xmlStrEqual(cur->name, BAD_CAST "source")) {
                 vhostuser_type = virXMLPropString(cur, "type");
-                if (!vhostuser_type || STREQ(vhostuser_type, "unix")) {
-                    vhostuser_path = virXMLPropString(cur, "path");
-                    vhostuser_mode = virXMLPropString(cur, "mode");
-                }
-                else {
-                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                                   _("type='%s' unsupported for"
-                                   " <interface type='vhostuser'>"),
-                                   vhostuser_type);
-                    goto error;
-                }
+                vhostuser_path = virXMLPropString(cur, "path");
+                vhostuser_mode = virXMLPropString(cur, "mode");
             } else if (!def->virtPortProfile
                        && xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
                 if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
@@ -6819,43 +6810,51 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
         break;
 
     case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
-        if (!model || STRNEQ(model, "virtio")) {
+        if (STRNEQ_NULLABLE(model, "virtio")) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("Wrong or no <model> 'type' attribute "
-                           "specified with <interface type='vhostuser'/>. "
-                           "vhostuser requires the virtio-net* frontend"));
+                             "specified with <interface type='vhostuser'/>. "
+                             "vhostuser requires the virtio-net* frontend"));
+            goto error;
+        }
+
+        if (STRNEQ_NULLABLE(vhostuser_type, "unix")) {
+            if (vhostuser_type)
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("type='%s' unsupported for"
+                                 " <interface type='vhostuser'>"),
+                               vhostuser_type);
+            else
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("no type specified for "
+                                 "<interface type='vhostuser'>"));
+            goto error;
+        }
+
+        if (vhostuser_path == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("No <source> 'path' attribute "
+                             "specified with <interface "
+                             "type='vhostuser'/>"));
+            goto error;
+        }
+
+        if (vhostuser_mode == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("No <source> 'mode' attribute "
+                             "specified with <interface "
+                             "type='vhostuser'/>"));
             goto error;
         }
 
         if (VIR_ALLOC(def->data.vhostuser) < 0)
             goto error;

-        if (STREQ(vhostuser_type, "unix")) {
+        def->data.vhostuser->type = VIR_DOMAIN_CHR_TYPE_UNIX;
+        def->data.vhostuser->data.nix.path = vhostuser_path;
 
-            (def->data.vhostuser)->type = VIR_DOMAIN_CHR_TYPE_UNIX;
-
-            if (vhostuser_path == NULL) {
-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("No <source> 'path' attribute "
-                               "specified with <interface "
-                               "type='vhostuser'/>"));
-                goto error;
-            }
-
-            (def->data.vhostuser)->data.nix.path = vhostuser_path;
-
-            if (vhostuser_mode == NULL) {
-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("No <source> 'mode' attribute "
-                               "specified with <interface "
-                               "type='vhostuser'/>"));
-                goto error;
-            }
-
-            if (STREQ(vhostuser_mode, "server"))
-                (def->data.vhostuser)->data.nix.listen = true;
-
-        }
+        if (STREQ(vhostuser_mode, "server"))
+            (def->data.vhostuser)->data.nix.listen = true;
 
         vhostuser_type = NULL;
         vhostuser_path = NULL;
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 0b4a0b5..a193a93 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -987,6 +987,7 @@ libxlMakeNic(virDomainDefPtr def,
             break;
         }
         case VIR_DOMAIN_NET_TYPE_USER:
+        case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
         case VIR_DOMAIN_NET_TYPE_SERVER:
         case VIR_DOMAIN_NET_TYPE_CLIENT:
         case VIR_DOMAIN_NET_TYPE_MCAST:
diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
index 7a206d2..1d5d689 100644
--- a/src/uml/uml_conf.c
+++ b/src/uml/uml_conf.c
@@ -248,6 +248,11 @@ umlBuildCommandLineNet(virConnectPtr conn,
                        _("hostdev networking type not supported"));
         goto error;
 
+    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("vhostuser networking type not supported"));
+        goto error;
+
     case VIR_DOMAIN_NET_TYPE_LAST:
         break;
     }
diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c
index 9e59804..3d46773 100644
--- a/src/xenxs/xen_sxpr.c
+++ b/src/xenxs/xen_sxpr.c
@@ -1932,6 +1932,7 @@ xenFormatSxprNet(virConnectPtr conn,
         break;
 
     case VIR_DOMAIN_NET_TYPE_USER:
+    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
     case VIR_DOMAIN_NET_TYPE_SERVER:
     case VIR_DOMAIN_NET_TYPE_CLIENT:
     case VIR_DOMAIN_NET_TYPE_MCAST:


Michal




More information about the libvir-list mailing list