On 02/13/2013 05:59 AM, Peter Krempa wrote:
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.
---
src/conf/domain_conf.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++-
src/conf/domain_conf.h | 37 +++++++++
src/libvirt_private.syms | 2 +
3 files changed, 234 insertions(+), 1 deletion(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7a2b012..a16d70b 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:
@@ -7403,6 +7416,109 @@ error:
}
+static virDomainRNGDefPtr
+virDomainRNGDefParseXML(const xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
+ unsigned int flags)
+{
+ const char *model;
+ const char *backend;
Init to 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;
+ }
model needs a VIR_FREE, right?
+
+ 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;
+ }
Does there need to be a specific/different message if nbackends == 0?
+
+ if (!(backend = virXMLPropString(backends[0], "model"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing RNG device backend model"));
+ goto error;
+ }
backend needs a VIR_FREE too, right?
+
+ 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;
+ }
type needs a VIR_FREE, right?
+
+
+ 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);
+ goto error;
+ }
+
+ 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:
+ ctxt->node = save;
+ return def;
+
+error:
+ virDomainRNGDefFree(def);
+ def = NULL;
+ goto cleanup;
+}
+
+
static virDomainMemballoonDefPtr
virDomainMemballoonDefParseXML(const xmlNodePtr node,
unsigned int flags)
@@ -8196,6 +8312,10 @@ virDomainDeviceDefPtr 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"));
@@ -10552,6 +10672,22 @@ static virDomainDefPtr 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 memory balloon device is supported"));
Looks like a cut-n-paste error ^^^^^^^^^^^^^^^^^^^^^
+ 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;
@@ -13614,6 +13750,61 @@ 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)
@@ -14812,6 +15003,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);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9232ff9..b78a04c 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;
@@ -2062,6 +2095,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);
@@ -2322,6 +2357,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 b9d45a2..814e66f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -498,6 +498,8 @@ virDomainPMSuspendedReasonTypeFromString;
virDomainPMSuspendedReasonTypeToString;
virDomainRedirdevBusTypeFromString;
virDomainRedirdevBusTypeToString;
+virDomainRNGBackendTypeToString;
+virDomainRNGModelTypeToString;
virDomainRunningReasonTypeFromString;
virDomainRunningReasonTypeToString;
virDomainSaveConfig;