[RFC PATCH 06/10] qemu_capabilities: Added capability for ebpf helper path.

Andrew Melnychenko andrew at daynix.com
Wed Jul 28 08:17:10 UTC 2021


Added qmp call to receive helper path.
Also added monitor functions.
For virQEMUCaps added field for helper path.
Libvirt queries "query-helper-paths" from qmp and saves in qemuCaps.
The qemu and the helper should be "sync" and the helper should
return proper eBPF fd and maps with "interface" for current qemu.
So, qemu returns where to find the helper through qmp, if the qemu supports
"ebpf_rss_fds".

Signed-off-by: Andrew Melnychenko <andrew at daynix.com>
---
 src/qemu/qemu_capabilities.c | 44 +++++++++++++++++++++++++++++++
 src/qemu/qemu_capabilities.h |  3 +++
 src/qemu/qemu_monitor.c      |  9 +++++++
 src/qemu/qemu_monitor.h      |  3 +++
 src/qemu/qemu_monitor_json.c | 50 ++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_json.h |  3 +++
 6 files changed, 112 insertions(+)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index f16115226d..f62088d32f 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -722,6 +722,9 @@ struct _virQEMUCaps {
     /* Capabilities which may differ depending on the accelerator. */
     virQEMUCapsAccel kvm;
     virQEMUCapsAccel tcg;
+
+    /* Helpers returned by qemu */
+    char *helperEbpfRSS;
 };
 
 struct virQEMUCapsSearchData {
@@ -1994,6 +1997,8 @@ virQEMUCaps *virQEMUCapsNewCopy(virQEMUCaps *qemuCaps)
                                qemuCaps->sevCapabilities) < 0)
         goto error;
 
+    ret->helperEbpfRSS = g_strdup(qemuCaps->helperEbpfRSS);
+
     return ret;
 
  error:
@@ -2037,6 +2042,8 @@ void virQEMUCapsDispose(void *obj)
 
     virQEMUCapsAccelClear(&qemuCaps->kvm);
     virQEMUCapsAccelClear(&qemuCaps->tcg);
+
+    g_free(qemuCaps->helperEbpfRSS);
 }
 
 void
@@ -4418,6 +4425,8 @@ virQEMUCapsLoadCache(virArch hostArch,
     if (virXPathBoolean("boolean(./kvmSupportsSecureGuest)", ctxt) > 0)
         qemuCaps->kvmSupportsSecureGuest = true;
 
+    qemuCaps->helperEbpfRSS = virXPathString("string(./EbpfHelperPath)", ctxt);
+
     if (skipInvalidation)
         qemuCaps->invalidation = false;
 
@@ -4671,6 +4680,10 @@ virQEMUCapsFormatCache(virQEMUCaps *qemuCaps)
     if (qemuCaps->kvmSupportsSecureGuest)
         virBufferAddLit(&buf, "<kvmSupportsSecureGuest/>\n");
 
+    if (qemuCaps->helperEbpfRSS) {
+        virBufferAsprintf(&buf, "<EbpfHelperPath>%s</EbpfHelperPath>\n", qemuCaps->helperEbpfRSS);
+    }
+
     virBufferAdjustIndent(&buf, -2);
     virBufferAddLit(&buf, "</qemuCaps>\n");
 
@@ -5265,6 +5278,30 @@ virQEMUCapsGetVirtType(virQEMUCaps *qemuCaps)
     return type;
 }
 
+static int
+virQEMUCapsProbeQMPHelperPath(virQEMUCaps *qemuCaps,
+                          qemuMonitor *mon)
+{
+    g_autoptr(GHashTable) helperList = NULL;
+    const char *entry = NULL;
+
+    helperList = qemuMonitorGetHelperPath(mon);
+
+    if (!helperList) {
+        return -1;
+    }
+
+    /* TODO: parse all helpers? */
+    entry = virHashLookup(helperList, "qemu-ebpf-rss-helper");
+    if (!entry) {
+        return -1;
+    }
+
+    qemuCaps->helperEbpfRSS = g_strdup(entry);
+
+    return 0;
+}
+
 int
 virQEMUCapsInitQMPMonitor(virQEMUCaps *qemuCaps,
                           qemuMonitor *mon)
@@ -5345,6 +5382,8 @@ virQEMUCapsInitQMPMonitor(virQEMUCaps *qemuCaps,
     if (virQEMUCapsProbeQMPHostCPU(qemuCaps, accel, mon, type) < 0)
         return -1;
 
+    virQEMUCapsProbeQMPHelperPath(qemuCaps, mon);
+
     return 0;
 }
 
@@ -6459,3 +6498,8 @@ virQEMUCapsStripMachineAliases(virQEMUCaps *qemuCaps)
     virQEMUCapsStripMachineAliasesForVirtType(qemuCaps, VIR_DOMAIN_VIRT_KVM);
     virQEMUCapsStripMachineAliasesForVirtType(qemuCaps, VIR_DOMAIN_VIRT_QEMU);
 }
+
+const char *virQEMUCapsGetEBPFHelperPath(virQEMUCaps *qemuCaps)
+{
+    return qemuCaps->helperEbpfRSS;
+}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index c938b63e91..b25bdd4ec3 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -816,3 +816,6 @@ virQEMUCapsGetKVMSupportsSecureGuest(virQEMUCaps *qemuCaps) G_GNUC_NO_INLINE;
 
 virArch virQEMUCapsArchFromString(const char *arch);
 const char *virQEMUCapsArchToString(virArch arch);
+
+const char *
+virQEMUCapsGetEBPFHelperPath(virQEMUCaps *qemuCaps);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 6e2d8010c5..585fb2d6b4 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4617,3 +4617,12 @@ qemuMonitorQueryDirtyRate(qemuMonitor *mon,
 
     return qemuMonitorJSONQueryDirtyRate(mon, info);
 }
+
+
+GHashTable *
+qemuMonitorGetHelperPath(qemuMonitor *mon)
+{
+    QEMU_CHECK_MONITOR_NULL(mon);
+
+    return qemuMonitorJSONGetHelperPath(mon);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 1491c1297c..0ee87d2c46 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1491,3 +1491,6 @@ struct _qemuMonitorDirtyRateInfo {
 int
 qemuMonitorQueryDirtyRate(qemuMonitor *mon,
                           qemuMonitorDirtyRateInfo *info);
+
+GHashTable *
+qemuMonitorGetHelperPath(qemuMonitor *mon);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index ca2c3bb6cf..0579eee36a 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -9387,3 +9387,53 @@ qemuMonitorJSONQueryDirtyRate(qemuMonitor *mon,
 
     return qemuMonitorJSONExtractDirtyRateInfo(data, info);
 }
+
+static int
+qemuMonitorJSONGetHelperPathWorker(size_t pos G_GNUC_UNUSED,
+                                    virJSONValue *item,
+                                    void *opaque)
+{
+    const char *name = virJSONValueObjectGetString(item, "name");
+    const char *path = virJSONValueObjectGetString(item, "path");
+    GHashTable *pathsList = opaque;
+
+    if (!name) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("reply data was missing 'name'"));
+        return -1;
+    }
+
+    if (virHashAddEntry(pathsList, name, g_strdup(path)) < 0)
+        return -1;
+
+    return 0;
+}
+
+GHashTable *
+qemuMonitorJSONGetHelperPath(qemuMonitor *mon)
+{
+    g_autoptr(GHashTable) pathsList = virHashNew(g_free);
+    g_autoptr(virJSONValue) cmd = NULL;
+    g_autoptr(virJSONValue) reply = NULL;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("query-helper-paths", NULL)))
+        return NULL;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return NULL;
+
+    /* return empty hash */
+    if (qemuMonitorJSONHasError(reply, "CommandNotFound"))
+        return g_steal_pointer(&pathsList);
+
+    if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
+        return NULL;
+
+    if (virJSONValueArrayForeachSteal(virJSONValueObjectGetArray(reply, "return"),
+            qemuMonitorJSONGetHelperPathWorker,
+            pathsList) < 0)
+        return NULL;
+
+    return g_steal_pointer(&pathsList);
+}
+
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 01a3ba25f1..80e47cf68f 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -706,3 +706,6 @@ qemuMonitorJSONStartDirtyRateCalc(qemuMonitor *mon,
 int
 qemuMonitorJSONQueryDirtyRate(qemuMonitor *mon,
                               qemuMonitorDirtyRateInfo *info);
+
+GHashTable *
+qemuMonitorJSONGetHelperPath(qemuMonitor *mon);
-- 
2.31.1




More information about the libvir-list mailing list