[RFC PATCH v3 2/6] qemu_capabilities: Added logic for retrieving eBPF objects from QEMU.

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

 



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




[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]

  Powered by Linux