[PATCHv2 3/8] conf: Add support for RNG device configuration in XML

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

 



This patch adds basic configuration support for the RNG device suporting
the virtio model with the "random" and "egd" backend types as described
in the schema in the previous patch.
---

Notes:
    Version 2:
    - fix a ton of memory leaks (I assumed that virXMLGetProp returns static strings)
    - Add new device type to even more places
    - Fix error message c&p error
    - Fix memleak in RNGDef free func

 src/conf/domain_conf.c   | 214 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/conf/domain_conf.h   |  37 ++++++++
 src/libvirt_private.syms |   2 +
 3 files changed, 252 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9e9fdb0..082f1f5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -175,7 +175,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
               "redirdev",
               "smartcard",
               "chr",
-              "memballoon")
+              "memballoon",
+              "rng")

 VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
               "none",
@@ -700,6 +701,15 @@ VIR_ENUM_IMPL(virDomainNumatuneMemPlacementMode,
               "static",
               "auto");

+VIR_ENUM_IMPL(virDomainRNGModel,
+              VIR_DOMAIN_RNG_MODEL_LAST,
+              "virtio");
+
+VIR_ENUM_IMPL(virDomainRNGBackend,
+              VIR_DOMAIN_RNG_BACKEND_LAST,
+              "random",
+              "egd");
+
 #define VIR_DOMAIN_XML_WRITE_FLAGS  VIR_DOMAIN_XML_SECURE
 #define VIR_DOMAIN_XML_READ_FLAGS   VIR_DOMAIN_XML_INACTIVE

@@ -1597,6 +1607,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
     case VIR_DOMAIN_DEVICE_REDIRDEV:
         virDomainRedirdevDefFree(def->data.redirdev);
         break;
+    case VIR_DOMAIN_DEVICE_RNG:
+        virDomainRNGDefFree(def->data.rng);
+        break;
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_FS:
     case VIR_DOMAIN_DEVICE_SMARTCARD:
@@ -2342,6 +2355,12 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def,
         if (cb(def, &device, &def->memballoon->info, opaque) < 0)
             return -1;
     }
+    if (def->rng) {
+        device.type = VIR_DOMAIN_DEVICE_RNG;
+        device.data.rng = def->rng;
+        if (cb(def, &device, &def->rng->info, opaque) < 0)
+            return -1;
+    }
     device.type = VIR_DOMAIN_DEVICE_HUB;
     for (i = 0; i < def->nhubs ; i++) {
         device.data.hub = def->hubs[i];
@@ -2374,6 +2393,7 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def,
     case VIR_DOMAIN_DEVICE_CHR:
     case VIR_DOMAIN_DEVICE_MEMBALLOON:
     case VIR_DOMAIN_DEVICE_LAST:
+    case VIR_DOMAIN_DEVICE_RNG:
         break;
     }

@@ -7452,6 +7472,115 @@ error:
 }


+static virDomainRNGDefPtr
+virDomainRNGDefParseXML(const xmlNodePtr node,
+                        xmlXPathContextPtr ctxt,
+                        unsigned int flags)
+{
+    const char *model = NULL;
+    const char *backend = NULL;
+    virDomainRNGDefPtr def;
+    xmlNodePtr save = ctxt->node;
+    xmlNodePtr *backends = NULL;
+    int nbackends;
+
+    if (VIR_ALLOC(def) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    if (!(model = virXMLPropString(node, "model"))) {
+        virReportError(VIR_ERR_XML_ERROR, "%s", _("missing RNG device model"));
+        goto error;
+    }
+
+    if ((def->model = virDomainRNGModelTypeFromString(model)) < 0) {
+        virReportError(VIR_ERR_XML_ERROR, _("unknown RNG model '%s'"), model);
+        goto error;
+    }
+
+    ctxt->node = node;
+
+    if ((nbackends = virXPathNodeSet("./backend", ctxt, &backends)) < 0)
+        goto error;
+
+    if (nbackends != 1) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("only one RNG backend is supported"));
+        goto error;
+    }
+
+    if (!(backend = virXMLPropString(backends[0], "model"))) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing RNG device backend model"));
+        goto error;
+    }
+
+    if ((def->backend = virDomainRNGBackendTypeFromString(backend)) < 0) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("unknown RNG backend model '%s'"), backend);
+        goto error;
+    }
+
+    switch ((enum virDomainRNGBackend) def->backend) {
+    case VIR_DOMAIN_RNG_BACKEND_RANDOM:
+        def->source.file = virXPathString("string(./backend)", ctxt);
+        break;
+
+    case VIR_DOMAIN_RNG_BACKEND_EGD:
+        {
+            char *type = virXMLPropString(backends[0], "type");
+            if (!type) {
+                virReportError(VIR_ERR_XML_ERROR, "%s",
+                               _("missing EGD backend type"));
+                goto error;
+            }
+
+
+            if (VIR_ALLOC(def->source.chardev) < 0) {
+                virReportOOMError();
+                goto error;
+            }
+
+            def->source.chardev->type = virDomainChrTypeFromString(type);
+            if (def->source.chardev->type < 0) {
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("unknown backend type '%s' for egd"),
+                               type);
+                VIR_FREE(type);
+                goto error;
+            }
+
+            VIR_FREE(type);
+
+            if (virDomainChrSourceDefParseXML(def->source.chardev,
+                                              backends[0]->children, flags,
+                                              NULL, ctxt, NULL, 0) < 0)
+                goto error;
+        }
+        break;
+
+    case VIR_DOMAIN_RNG_BACKEND_LAST:
+        break;
+    }
+
+    if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
+        goto error;
+
+cleanup:
+    VIR_FREE(model);
+    VIR_FREE(backend);
+    VIR_FREE(backends);
+    ctxt->node = save;
+    return def;
+
+error:
+    virDomainRNGDefFree(def);
+    def = NULL;
+    goto cleanup;
+}
+
+
 static virDomainMemballoonDefPtr
 virDomainMemballoonDefParseXML(const xmlNodePtr node,
                                unsigned int flags)
@@ -8247,6 +8376,10 @@ virDomainDeviceDefParse(virCapsPtr caps,
         dev->type = VIR_DOMAIN_DEVICE_REDIRDEV;
         if (!(dev->data.redirdev = virDomainRedirdevDefParseXML(node, NULL, flags)))
             goto error;
+    } else if (xmlStrEqual(node->name, BAD_CAST "rng")) {
+        dev->type = VIR_DOMAIN_DEVICE_RNG;
+        if (!(dev->data.rng = virDomainRNGDefParseXML(node, ctxt, flags)))
+            goto error;
     } else {
         virReportError(VIR_ERR_XML_ERROR,
                        "%s", _("unknown device type"));
@@ -10601,6 +10734,22 @@ virDomainDefParseXML(virCapsPtr caps,
         }
     }

+    /* Parse the RNG device */
+    if ((n = virXPathNodeSet("./devices/rng", ctxt, &nodes)) < 0)
+        goto error;
+
+    if (n > 1) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("only a single RNG device is supported"));
+        goto error;
+    }
+
+    if (n > 0) {
+        if (!(def->rng = virDomainRNGDefParseXML(nodes[0], ctxt, flags)))
+            goto error;
+        VIR_FREE(nodes);
+    }
+
     /* analysis of the hub devices */
     if ((n = virXPathNodeSet("./devices/hub", ctxt, &nodes)) < 0) {
         goto error;
@@ -13623,6 +13772,63 @@ virDomainWatchdogDefFormat(virBufferPtr buf,
 }


+static int
+virDomainRNGDefFormat(virBufferPtr buf,
+                      virDomainRNGDefPtr def,
+                      unsigned int flags)
+{
+    const char *model = virDomainRNGModelTypeToString(def->model);
+    const char *backend = virDomainRNGBackendTypeToString(def->backend);
+
+    virBufferAsprintf(buf, "    <rng model='%s'>\n", model);
+    virBufferAsprintf(buf, "      <backend model='%s'", backend);
+
+    switch ((enum virDomainRNGBackend) def->backend) {
+    case VIR_DOMAIN_RNG_BACKEND_RANDOM:
+        if (def->source.file)
+            virBufferAsprintf(buf, ">%s</backend>\n", def->source.file);
+        else
+            virBufferAddLit(buf, "/>\n");
+
+        break;
+
+    case VIR_DOMAIN_RNG_BACKEND_EGD:
+        virBufferAdjustIndent(buf, 2);
+        if (virDomainChrSourceDefFormat(buf, def->source.chardev,
+                                        false, flags) < 0)
+            return -1;
+        virBufferAdjustIndent(buf, -2);
+        virBufferAddLit(buf, "      </backend>\n");
+
+    case VIR_DOMAIN_RNG_BACKEND_LAST:
+        break;
+    }
+
+    virBufferAddLit(buf, "    </rng>\n");
+
+    return 0;
+}
+
+void
+virDomainRNGDefFree(virDomainRNGDefPtr def)
+{
+    if (!def)
+        return;
+
+    switch ((enum virDomainRNGBackend) def->backend) {
+    case VIR_DOMAIN_RNG_BACKEND_RANDOM:
+        VIR_FREE(def->source.file);
+        break;
+    case VIR_DOMAIN_RNG_BACKEND_EGD:
+        virDomainChrSourceDefFree(def->source.chardev);
+        break;
+    case VIR_DOMAIN_RNG_BACKEND_LAST:
+        break;
+    }
+
+    VIR_FREE(def);
+}
+
 static void
 virDomainVideoAccelDefFormat(virBufferPtr buf,
                              virDomainVideoAccelDefPtr def)
@@ -14816,6 +15022,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
     if (def->memballoon)
         virDomainMemballoonDefFormat(buf, def->memballoon, flags);

+    if (def->rng)
+        virDomainRNGDefFormat(buf, def->rng, flags);
+
     virBufferAddLit(buf, "  </devices>\n");

     virBufferAdjustIndent(buf, 2);
@@ -16086,6 +16295,9 @@ virDomainDeviceDefCopy(virCapsPtr caps,
     case VIR_DOMAIN_DEVICE_REDIRDEV:
         rc = virDomainRedirdevDefFormat(&buf, src->data.redirdev, flags);
         break;
+    case VIR_DOMAIN_DEVICE_RNG:
+        rc = virDomainRNGDefFormat(&buf, src->data.rng, flags);
+        break;
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_SMARTCARD:
     case VIR_DOMAIN_DEVICE_CHR:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 4ffa4aa..0828954 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -114,6 +114,9 @@ typedef virDomainSnapshotObj *virDomainSnapshotObjPtr;
 typedef struct _virDomainSnapshotObjList virDomainSnapshotObjList;
 typedef virDomainSnapshotObjList *virDomainSnapshotObjListPtr;

+typedef struct _virDomainRNGDef virDomainRNGDef;
+typedef virDomainRNGDef *virDomainRNGDefPtr;
+
 /* Flags for the 'type' field in virDomainDeviceDef */
 typedef enum {
     VIR_DOMAIN_DEVICE_NONE = 0,
@@ -133,6 +136,7 @@ typedef enum {
     VIR_DOMAIN_DEVICE_SMARTCARD,
     VIR_DOMAIN_DEVICE_CHR,
     VIR_DOMAIN_DEVICE_MEMBALLOON,
+    VIR_DOMAIN_DEVICE_RNG,

     VIR_DOMAIN_DEVICE_LAST
 } virDomainDeviceType;
@@ -158,6 +162,7 @@ struct _virDomainDeviceDef {
         virDomainSmartcardDefPtr smartcard;
         virDomainChrDefPtr chr;
         virDomainMemballoonDefPtr memballoon;
+        virDomainRNGDefPtr rng;
     } data;
 };

@@ -1714,6 +1719,33 @@ struct _virBlkioDeviceWeight {
     unsigned int weight;
 };

+enum virDomainRNGModel {
+    VIR_DOMAIN_RNG_MODEL_VIRTIO,
+
+    VIR_DOMAIN_RNG_MODEL_LAST
+};
+
+enum virDomainRNGBackend {
+    VIR_DOMAIN_RNG_BACKEND_RANDOM,
+    VIR_DOMAIN_RNG_BACKEND_EGD,
+    /* VIR_DOMAIN_RNG_BACKEND_POOL, */
+
+    VIR_DOMAIN_RNG_BACKEND_LAST
+};
+
+struct _virDomainRNGDef {
+    int model;
+    int backend;
+
+    union {
+        char *file; /* file name for 'random' source */
+        virDomainChrSourceDefPtr chardev; /* a char backend for
+                                             the EGD source */
+    } source;
+
+    virDomainDeviceInfo info;
+};
+
 void virBlkioDeviceWeightArrayClear(virBlkioDeviceWeightPtr deviceWeights,
                                     int ndevices);

@@ -1852,6 +1884,7 @@ struct _virDomainDef {
     virCPUDefPtr cpu;
     virSysinfoDefPtr sysinfo;
     virDomainRedirFilterDefPtr redirfilter;
+    virDomainRNGDefPtr rng;

     void *namespaceData;
     virDomainXMLNamespace ns;
@@ -2065,6 +2098,8 @@ int virDomainEmulatorPinAdd(virDomainDefPtr def,

 int virDomainEmulatorPinDel(virDomainDefPtr def);

+void virDomainRNGDefFree(virDomainRNGDefPtr def);
+
 int virDomainDiskIndexByName(virDomainDefPtr def, const char *name,
                              bool allow_ambiguous);
 const char *virDomainDiskPathByName(virDomainDefPtr, const char *name);
@@ -2325,6 +2360,8 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode)
 VIR_ENUM_DECL(virDomainNumatuneMemMode)
 VIR_ENUM_DECL(virDomainNumatuneMemPlacementMode)
 VIR_ENUM_DECL(virDomainHyperv)
+VIR_ENUM_DECL(virDomainRNGModel)
+VIR_ENUM_DECL(virDomainRNGBackend)
 /* from libvirt.h */
 VIR_ENUM_DECL(virDomainState)
 VIR_ENUM_DECL(virDomainNostateReason)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f399871..aed007e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -286,6 +286,8 @@ virDomainPMSuspendedReasonTypeFromString;
 virDomainPMSuspendedReasonTypeToString;
 virDomainRedirdevBusTypeFromString;
 virDomainRedirdevBusTypeToString;
+virDomainRNGBackendTypeToString;
+virDomainRNGModelTypeToString;
 virDomainRunningReasonTypeFromString;
 virDomainRunningReasonTypeToString;
 virDomainSaveConfig;
-- 
1.8.1.1

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]