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@daynix.com>
---
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@lists.libvirt.org
To unsubscribe send an email to devel-leave@lists.libvirt.org
On 5/12/24 21:45, Andrew Melnychenko wrote: > 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@daynix.com> > --- > src/qemu/qemu_capabilities.c | 122 +++++++++++++++++++++++++++++++++++ > src/qemu/qemu_capabilities.h | 3 + > 2 files changed, 125 insertions(+) 'meson test' fails after this one. > > 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)); > + } > + I'd move this into a separate function for code estetics purpose. > return g_steal_pointer(&ret); > } Michal
© 2016 - 2024 Red Hat, Inc.