eBPF objects stored in the hash table during runtime. eBPF objects cached encoded in base64 in the .xml cache file. Signed-off-by: Andrew Melnychenko <andrew@xxxxxxxxxx> --- src/qemu/qemu_capabilities.c | 122 +++++++++++++++++++++++++++++++++++ src/qemu/qemu_capabilities.h | 3 + 2 files changed, 125 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 45525db803..09bb6ca36e 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -799,6 +799,9 @@ struct _virQEMUCaps { virQEMUCapsAccel kvm; virQEMUCapsAccel hvf; virQEMUCapsAccel tcg; + + /* Hash of ebpf objects encoded in base64 */ + GHashTable *ebpfObjects; }; struct virQEMUCapsSearchData { @@ -846,6 +849,13 @@ const char *virQEMUCapsArchToString(virArch arch) } +const char * +virQEMUCapsGetEbpf(virQEMUCaps *qemuCaps, const char *id) +{ + return virHashLookup(qemuCaps->ebpfObjects, id); +} + + /* Checks whether a domain with @guest arch can run natively on @host. */ bool @@ -1823,6 +1833,8 @@ virQEMUCapsNew(void) qemuCaps->invalidation = true; qemuCaps->flags = virBitmapNew(QEMU_CAPS_LAST); + qemuCaps->ebpfObjects = virHashNew(g_free); + return qemuCaps; } @@ -1965,6 +1977,9 @@ virQEMUCaps *virQEMUCapsNewCopy(virQEMUCaps *qemuCaps) { g_autoptr(virQEMUCaps) ret = virQEMUCapsNewBinary(qemuCaps->binary); size_t i; + GHashTableIter iter; + const char *key; + const char *value; ret->invalidation = qemuCaps->invalidation; ret->kvmSupportsNesting = qemuCaps->kvmSupportsNesting; @@ -2003,6 +2018,12 @@ virQEMUCaps *virQEMUCapsNewCopy(virQEMUCaps *qemuCaps) ret->hypervCapabilities = g_memdup(qemuCaps->hypervCapabilities, sizeof(virDomainCapsFeatureHyperv)); + ret->ebpfObjects = virHashNew(g_free); + g_hash_table_iter_init(&iter, qemuCaps->ebpfObjects); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { + g_hash_table_insert(ret->ebpfObjects, g_strdup(key), g_strdup(value)); + } + return g_steal_pointer(&ret); } @@ -2045,6 +2066,8 @@ void virQEMUCapsDispose(void *obj) g_free(qemuCaps->hypervCapabilities); + g_hash_table_destroy(qemuCaps->ebpfObjects); + virQEMUCapsAccelClear(&qemuCaps->kvm); virQEMUCapsAccelClear(&qemuCaps->hvf); virQEMUCapsAccelClear(&qemuCaps->tcg); @@ -4560,6 +4583,40 @@ virQEMUCapsValidateArch(virQEMUCaps *qemuCaps, xmlXPathContextPtr ctxt) } +static int +virQEMUCapsParseEbpfObjects(virQEMUCaps *qemuCaps, xmlXPathContextPtr ctxt) +{ + g_autofree xmlNodePtr *nodes = NULL; + size_t i; + int n; + + if ((n = virXPathNodeSet("./ebpf/object", ctxt, &nodes)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse qemu cached eBPF object")); + return -1; + } + + for (i = 0; i < n; i++) { + g_autofree char *id = NULL; + g_autofree char *ebpf = NULL; + + if (!(id = virXMLPropStringRequired(nodes[i], "id"))) + return -1; + + if (!(ebpf = virXMLPropStringRequired(nodes[i], "data"))) + return -1; + + if (virHashAddEntry(qemuCaps->ebpfObjects, id, ebpf) < 0) + return -1; + + /* steal the ebpf if it was added to the hash without issues */ + g_steal_pointer(&ebpf); + } + + return 0; +} + + /* * Parsing a doc that looks like * @@ -4707,6 +4764,9 @@ virQEMUCapsLoadCache(virArch hostArch, if (skipInvalidation) qemuCaps->invalidation = false; + if (virQEMUCapsParseEbpfObjects(qemuCaps, ctxt) < 0) + return -1; + return 0; } @@ -4944,6 +5004,16 @@ virQEMUCapsFormatHypervCapabilities(virQEMUCaps *qemuCaps, } +static int +virQEMUCapsFormatEbpfObjectsIterator(void *payload, const char *name, void *opaque) +{ + virBuffer *buf = opaque; + + virBufferAsprintf(buf, "<object id='%s' data='%s'/>\n", name, (const char *)payload); + + return 0; +} + char * virQEMUCapsFormatCache(virQEMUCaps *qemuCaps) { @@ -5034,6 +5104,14 @@ virQEMUCapsFormatCache(virQEMUCaps *qemuCaps) if (qemuCaps->kvmSupportsSecureGuest) virBufferAddLit(&buf, "<kvmSupportsSecureGuest/>\n"); + if (virHashSize(qemuCaps->ebpfObjects) > 0) { + virBufferAddLit(&buf, "<ebpf>\n"); + virBufferAdjustIndent(&buf, 2); + virHashForEachSorted(qemuCaps->ebpfObjects, virQEMUCapsFormatEbpfObjectsIterator, &buf); + virBufferAdjustIndent(&buf, -2); + virBufferAddLit(&buf, "</ebpf>\n"); + } + virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</qemuCaps>\n"); @@ -5456,6 +5534,47 @@ virQEMUCapsInitProcessCaps(virQEMUCaps *qemuCaps) } +static int +virQEMUCapsProbeQMPEbpfObject(virQEMUCaps *qemuCaps, const char *id, qemuMonitor *mon) +{ + const char *ebpfObject = NULL; + + ebpfObject = qemuMonitorGetEbpf(mon, id); + if (ebpfObject == NULL) + return -1; + + return virHashAddEntry(qemuCaps->ebpfObjects, id, (void *)ebpfObject); +} + + +static int +virQEMUCapsProbeQMPSchemaEbpf(virQEMUCaps *qemuCaps, GHashTable *schema, qemuMonitor *mon) +{ + virJSONValue *ebpfIdsArray; + virJSONValue *ebpfIdsSchema; + size_t i; + + if (virQEMUQAPISchemaPathGet("request-ebpf/arg-type/id", schema, &ebpfIdsSchema) != 1) + return 0; + + if (!(ebpfIdsArray = virJSONValueObjectGetArray(ebpfIdsSchema, "values"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed QMP schema of 'request-ebpf'")); + return -1; + } + + /* Try to request every eBPF */ + for (i = 0; i < virJSONValueArraySize(ebpfIdsArray); i++) { + virJSONValue *id = virJSONValueArrayGet(ebpfIdsArray, i); + + if (virQEMUCapsProbeQMPEbpfObject(qemuCaps, virJSONValueGetString(id), mon) < 0) + return -1; + } + + return 0; +} + + static int virQEMUCapsProbeQMPSchemaCapabilities(virQEMUCaps *qemuCaps, qemuMonitor *mon) @@ -5489,6 +5608,9 @@ virQEMUCapsProbeQMPSchemaCapabilities(virQEMUCaps *qemuCaps, virQEMUQAPISchemaPathExists("block-stream/arg-type/backing-mask-protocol", schema)) virQEMUCapsSet(qemuCaps, QEMU_CAPS_BLOCKJOB_BACKING_MASK_PROTOCOL); + if (virQEMUCapsProbeQMPSchemaEbpf(qemuCaps, schema, mon) < 0) + return -1; + return 0; } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 00b4066e9a..371ea19bd0 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -906,3 +906,6 @@ int virQEMUCapsProbeQMPMachineTypes(virQEMUCaps *qemuCaps, virDomainVirtType virtType, qemuMonitor *mon); + +const char * +virQEMUCapsGetEbpf(virQEMUCaps *qemuCaps, const char *id); -- 2.44.0 _______________________________________________ Devel mailing list -- devel@xxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxx