[RFC PATCH v4 0/5] Added virtio-net RSS with eBPF support.

This series of rfc patches adds support for loading the RSS eBPF program and passing it to the QEMU. Comments and suggestions would be useful. QEMU with vhost may work with RSS through eBPF. To load eBPF, the capabilities required that Libvirt may provide. eBPF program and maps may be unique for particular QEMU and Libvirt retrieves eBPF through qapi. For now, there is only "RSS" eBPF object in QEMU, in the future, there may be another one(g.e. network filters). That's why in Libvirt added logic to load and store any eBPF object that QEMU provides using qapi schema. One of the reasons why this series of patches is in RFC are tests. To this series of patches, the tests were added. For now, the tests are synthetic, the proper "reply" file should be generated with a new "caps" file. Currently, there are changes in caps-9.0.0* and caps-9.1.0 files. There was added support for ebpf_rss_fds feature, and request-ebpf command. So, overall, the tests are required for review, comment, and discussion how we want them to be implemented in the future. For virtio-net RSS, the document has not changed. ``` <interface type="network"> <model type="virtio"/> <driver queues="4" rss="on" rss_hash_report="off"/> <interface type="network"> ``` Simplified routine for RSS: * Libvirt retrieves eBPF "RSS" and load it. * Libvirt passes file descriptors to virtio-net with property "ebpf_rss_fds" ("rss" property should be "on" too). * if fds was provided - QEMU using eBPF RSS implementation. * if fds was not provided - QEMU tries to load eBPF RSS in own context and use it. * if eBPF RSS was not loaded - QEMU uses "in-qemu" RSS(vhost not supported). Changes since RFC v3: * changed tests a bit * refactored and rebased * removed "allowEBPF" from qemu config(now env is used for tests) Changes since RFC v2: * refactored and rebased. * applied changes according to the Qemu. * added basic test. Changes since RFC v1: * changed eBPF format saved in the XML cache. * refactored and checked with syntax test. * refactored patch hunks. Andrew Melnychenko (5): qemu_monitor: Added QEMU's "request-ebpf" support. qemu_capabilities: Added logic for retrieving eBPF objects from QEMU. qemu_interface: Added routine for loading the eBPF objects. qemu_command: Added "ebpf_rss_fds" support for virtio-net. tests: Added tests for eBPF blob loading. libvirt.spec.in | 3 + meson.build | 7 + meson_options.txt | 1 + src/qemu/meson.build | 1 + src/qemu/qemu_capabilities.c | 132 ++++++++++++ src/qemu/qemu_capabilities.h | 5 + src/qemu/qemu_command.c | 60 ++++++ src/qemu/qemu_domain.c | 4 + src/qemu/qemu_domain.h | 3 + src/qemu/qemu_interface.c | 87 ++++++++ src/qemu/qemu_interface.h | 7 + src/qemu/qemu_monitor.c | 9 + src/qemu/qemu_monitor.h | 4 + src/qemu/qemu_monitor_json.c | 27 +++ src/qemu/qemu_monitor_json.h | 4 + .../caps_9.0.0_sparc.replies | 95 +++++---- .../qemucapabilitiesdata/caps_9.0.0_sparc.xml | 3 + .../caps_9.0.0_x86_64.replies | 199 ++++++++++-------- .../caps_9.0.0_x86_64.xml | 4 + .../caps_9.1.0_x86_64.replies | 199 ++++++++++-------- .../caps_9.1.0_x86_64.xml | 4 + tests/qemuxml2argvmock.c | 24 +++ .../net-virtio-rss-bpf.x86_64-latest.args | 37 ++++ .../net-virtio-rss-bpf.x86_64-latest.xml | 46 ++++ tests/qemuxmlconfdata/net-virtio-rss-bpf.xml | 46 ++++ tests/qemuxmlconftest.c | 5 + 26 files changed, 792 insertions(+), 224 deletions(-) create mode 100644 tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/net-virtio-rss-bpf.xml -- 2.45.2

Added code for monitor and monitor_json. The "request-ebpf" return's eBPF binary object encoded in base64. QEMU provides eBPF that can be loaded and passed to it from Libvirt. QEMU requires exact eBPF program/maps, so it can be retrieved using QAPI. To load eBPF program - administrative capabilities are required, so Libvirt may load it and pass it to the QEMU instance. For now, there is only "RSS"(Receive Side Scaling) for virtio-net eBPF program and maps. Signed-off-by: Andrew Melnychenko <andrew@daynix.com> --- src/qemu/qemu_monitor.c | 9 +++++++++ src/qemu/qemu_monitor.h | 4 ++++ src/qemu/qemu_monitor_json.c | 27 +++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 4 ++++ 4 files changed, 44 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index b1c0c6a064..82729279ff 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4508,3 +4508,12 @@ qemuMonitorDisplayReload(qemuMonitor *mon, return qemuMonitorJSONDisplayReload(mon, type, tlsCerts); } + +const char * +qemuMonitorGetEbpf(qemuMonitor *mon, + const char *ebpfName) +{ + QEMU_CHECK_MONITOR_NULL(mon); + + return qemuMonitorJSONGetEbpf(mon, ebpfName); +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 76c859a888..720e9efbb8 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1617,3 +1617,7 @@ int qemuMonitorDisplayReload(qemuMonitor *mon, const char *type, bool tlsCerts); + +const char * +qemuMonitorGetEbpf(qemuMonitor *mon, + const char *ebpfName); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 8a20ce57e6..92bc7bd062 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8955,3 +8955,30 @@ int qemuMonitorJSONDisplayReload(qemuMonitor *mon, return 0; } + +const char * +qemuMonitorJSONGetEbpf(qemuMonitor *mon, + const char *ebpfName) +{ + g_autoptr(virJSONValue) cmd = NULL; + g_autoptr(virJSONValue) reply = NULL; + virJSONValue *ret = NULL; + + if (!(cmd = qemuMonitorJSONMakeCommand("request-ebpf", "s:id", ebpfName, NULL))) + return NULL; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + return NULL; + + if (qemuMonitorJSONCheckError(cmd, reply) < 0) + return NULL; + + ret = virJSONValueObjectGet(reply, "return"); + if (!ret) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("request-ebpf reply was missing 'return' data")); + return NULL; + } + + return g_strdup(virJSONValueObjectGetString(ret, "object")); +} diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 921dd34ed2..161f6b909f 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -825,3 +825,7 @@ qemuMonitorJSONQueryStats(qemuMonitor *mon, int qemuMonitorJSONDisplayReload(qemuMonitor *mon, const char *type, bool tlsCerts); + +const char * +qemuMonitorJSONGetEbpf(qemuMonitor *mon, + const char *ebpfName); -- 2.45.2

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 | 130 ++++++++++++ src/qemu/qemu_capabilities.h | 4 + .../caps_9.0.0_sparc.replies | 95 +++++---- .../qemucapabilitiesdata/caps_9.0.0_sparc.xml | 3 + .../caps_9.0.0_x86_64.replies | 199 ++++++++++-------- .../caps_9.0.0_x86_64.xml | 3 + .../caps_9.1.0_x86_64.replies | 199 ++++++++++-------- .../caps_9.1.0_x86_64.xml | 3 + 8 files changed, 412 insertions(+), 224 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 29dfe8d35a..2d2603e519 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -804,6 +804,9 @@ struct _virQEMUCaps { virQEMUCapsAccel kvm; virQEMUCapsAccel hvf; virQEMUCapsAccel tcg; + + /* Hash of ebpf objects encoded in base64 */ + GHashTable *ebpfObjects; }; static virClass *virQEMUCapsClass; @@ -845,6 +848,14 @@ 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 @@ -1824,6 +1835,8 @@ virQEMUCapsNew(void) qemuCaps->invalidation = true; qemuCaps->flags = virBitmapNew(QEMU_CAPS_LAST); + qemuCaps->ebpfObjects = virHashNew(g_free); + return qemuCaps; } @@ -1966,6 +1979,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; @@ -2004,6 +2020,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); } @@ -2046,6 +2068,8 @@ void virQEMUCapsDispose(void *obj) g_free(qemuCaps->hypervCapabilities); + g_hash_table_destroy(qemuCaps->ebpfObjects); + virQEMUCapsAccelClear(&qemuCaps->kvm); virQEMUCapsAccelClear(&qemuCaps->hvf); virQEMUCapsAccelClear(&qemuCaps->tcg); @@ -4563,6 +4587,41 @@ 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 * @@ -4710,6 +4769,9 @@ virQEMUCapsLoadCache(virArch hostArch, if (skipInvalidation) qemuCaps->invalidation = false; + if (virQEMUCapsParseEbpfObjects(qemuCaps, ctxt) < 0) + return -1; + return 0; } @@ -4947,6 +5009,18 @@ 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) { @@ -5037,6 +5111,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"); @@ -5453,6 +5535,51 @@ 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) @@ -5486,6 +5613,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 51d951771d..2c53236132 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -917,3 +917,7 @@ int virQEMUCapsProbeQMPMachineTypes(virQEMUCaps *qemuCaps, virDomainVirtType virtType, qemuMonitor *mon); + +const char * +virQEMUCapsGetEbpf(virQEMUCaps *qemuCaps, + const char *id); diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_sparc.replies b/tests/qemucapabilitiesdata/caps_9.0.0_sparc.replies index 9ddfcfae21..e1f46336c9 100644 --- a/tests/qemucapabilitiesdata/caps_9.0.0_sparc.replies +++ b/tests/qemucapabilitiesdata/caps_9.0.0_sparc.replies @@ -23356,21 +23356,36 @@ } { - "execute": "query-kvm", + "execute": "request-ebpf", + "arguments": { + "id": "rss" + }, "id": "libvirt-5" } +{ + "return": { + "object": "Test data" + }, + "id": "libvirt-5" +} + +{ + "execute": "query-kvm", + "id": "libvirt-6" +} + { "return": { "enabled": false, "present": false }, - "id": "libvirt-5" + "id": "libvirt-6" } { "execute": "qom-list-types", - "id": "libvirt-6" + "id": "libvirt-7" } { @@ -23976,7 +23991,7 @@ "parent": "base-sysbus-fdc" } ], - "id": "libvirt-6" + "id": "libvirt-7" } { @@ -23984,11 +23999,11 @@ "arguments": { "typename": "virtio-blk-pci" }, - "id": "libvirt-7" + "id": "libvirt-8" } { - "id": "libvirt-7", + "id": "libvirt-8", "error": { "class": "DeviceNotFound", "desc": "Device 'virtio-blk-pci' not found" @@ -24000,7 +24015,7 @@ "arguments": { "typename": "scsi-hd" }, - "id": "libvirt-8" + "id": "libvirt-9" } { @@ -24201,7 +24216,7 @@ "type": "int32" } ], - "id": "libvirt-8" + "id": "libvirt-9" } { @@ -24209,11 +24224,11 @@ "arguments": { "typename": "ide-hd" }, - "id": "libvirt-9" + "id": "libvirt-10" } { - "id": "libvirt-9", + "id": "libvirt-10", "error": { "class": "DeviceNotFound", "desc": "Device 'ide-hd' not found" @@ -24225,11 +24240,11 @@ "arguments": { "typename": "PIIX4_PM" }, - "id": "libvirt-10" + "id": "libvirt-11" } { - "id": "libvirt-10", + "id": "libvirt-11", "error": { "class": "DeviceNotFound", "desc": "Device 'PIIX4_PM' not found" @@ -24241,11 +24256,11 @@ "arguments": { "typename": "kvm-pit" }, - "id": "libvirt-11" + "id": "libvirt-12" } { - "id": "libvirt-11", + "id": "libvirt-12", "error": { "class": "DeviceNotFound", "desc": "Device 'kvm-pit' not found" @@ -24257,11 +24272,11 @@ "arguments": { "typename": "ICH9-LPC" }, - "id": "libvirt-12" + "id": "libvirt-13" } { - "id": "libvirt-12", + "id": "libvirt-13", "error": { "class": "DeviceNotFound", "desc": "Device 'ICH9-LPC' not found" @@ -24273,11 +24288,11 @@ "arguments": { "typename": "virtio-balloon-pci" }, - "id": "libvirt-13" + "id": "libvirt-14" } { - "id": "libvirt-13", + "id": "libvirt-14", "error": { "class": "DeviceNotFound", "desc": "Device 'virtio-balloon-pci' not found" @@ -24289,11 +24304,11 @@ "arguments": { "typename": "virtio-balloon-ccw" }, - "id": "libvirt-14" + "id": "libvirt-15" } { - "id": "libvirt-14", + "id": "libvirt-15", "error": { "class": "DeviceNotFound", "desc": "Device 'virtio-balloon-ccw' not found" @@ -24305,11 +24320,11 @@ "arguments": { "typename": "virtio-balloon-device" }, - "id": "libvirt-15" + "id": "libvirt-16" } { - "id": "libvirt-15", + "id": "libvirt-16", "error": { "class": "DeviceNotFound", "desc": "Device 'virtio-balloon-device' not found" @@ -24321,11 +24336,11 @@ "arguments": { "typename": "usb-host" }, - "id": "libvirt-16" + "id": "libvirt-17" } { - "id": "libvirt-16", + "id": "libvirt-17", "error": { "class": "DeviceNotFound", "desc": "Device 'usb-host' not found" @@ -24337,7 +24352,7 @@ "arguments": { "typename": "memory-backend-file" }, - "id": "libvirt-17" + "id": "libvirt-18" } { @@ -24431,7 +24446,7 @@ "type": "bool" } ], - "id": "libvirt-17" + "id": "libvirt-18" } { @@ -24439,7 +24454,7 @@ "arguments": { "typename": "memory-backend-memfd" }, - "id": "libvirt-18" + "id": "libvirt-19" } { @@ -24518,12 +24533,12 @@ "type": "int" } ], - "id": "libvirt-18" + "id": "libvirt-19" } { "execute": "query-machines", - "id": "libvirt-19" + "id": "libvirt-20" } { @@ -24639,7 +24654,7 @@ "default-ram-id": "ram" } ], - "id": "libvirt-19" + "id": "libvirt-20" } { @@ -24647,7 +24662,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-20" + "id": "libvirt-21" } { @@ -24760,32 +24775,32 @@ "type": "child<container>" } ], - "id": "libvirt-20" + "id": "libvirt-21" } { "execute": "query-tpm-models", - "id": "libvirt-21" + "id": "libvirt-22" } { "return": [], - "id": "libvirt-21" + "id": "libvirt-22" } { "execute": "query-tpm-types", - "id": "libvirt-22" + "id": "libvirt-23" } { "return": [], - "id": "libvirt-22" + "id": "libvirt-23" } { "execute": "query-command-line-options", - "id": "libvirt-23" + "id": "libvirt-24" } { @@ -26118,12 +26133,12 @@ "option": "drive" } ], - "id": "libvirt-23" + "id": "libvirt-24" } { "execute": "query-migrate-capabilities", - "id": "libvirt-24" + "id": "libvirt-25" } { @@ -26225,5 +26240,5 @@ "capability": "mapped-ram" } ], - "id": "libvirt-24" + "id": "libvirt-25" } diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml b/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml index 7fe971fc3a..3fbc83124a 100644 --- a/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml +++ b/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml @@ -93,4 +93,7 @@ <machine type='tcg' name='SS-600MP' maxCpus='4' defaultCPU='TI-SuperSparc-II-sparc-cpu' defaultRAMid='sun4m.ram' acpi='no'/> <machine type='tcg' name='SS-10' maxCpus='4' defaultCPU='TI-SuperSparc-II-sparc-cpu' defaultRAMid='sun4m.ram' acpi='no'/> <machine type='tcg' name='Voyager' maxCpus='1' defaultCPU='Fujitsu-MB86904-sparc-cpu' defaultRAMid='sun4m.ram' acpi='no'/> + <ebpf> + <object id='rss' data='Test data'/> + </ebpf> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.replies b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.replies index 5d36853ce3..b94625904b 100644 --- a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.replies @@ -23654,21 +23654,36 @@ } { - "execute": "query-kvm", + "execute": "request-ebpf", + "arguments": { + "id": "rss" + }, + "id": "libvirt-5" +} + +{ + "return": { + "object": "Test data" + }, "id": "libvirt-5" } +{ + "execute": "query-kvm", + "id": "libvirt-6" +} + { "return": { "enabled": true, "present": true }, - "id": "libvirt-5" + "id": "libvirt-6" } { "execute": "qom-list-types", - "id": "libvirt-6" + "id": "libvirt-7" } { @@ -26378,7 +26393,7 @@ "parent": "x86_64-cpu" } ], - "id": "libvirt-6" + "id": "libvirt-7" } { @@ -26386,7 +26401,7 @@ "arguments": { "typename": "virtio-blk-pci" }, - "id": "libvirt-7" + "id": "libvirt-8" } { @@ -26801,7 +26816,7 @@ "type": "bool" } ], - "id": "libvirt-7" + "id": "libvirt-8" } { @@ -26809,7 +26824,7 @@ "arguments": { "typename": "virtio-net-pci" }, - "id": "libvirt-8" + "id": "libvirt-9" } { @@ -27268,7 +27283,7 @@ "type": "bool" } ], - "id": "libvirt-8" + "id": "libvirt-9" } { @@ -27276,7 +27291,7 @@ "arguments": { "typename": "virtio-scsi-pci" }, - "id": "libvirt-9" + "id": "libvirt-10" } { @@ -27542,7 +27557,7 @@ "type": "child<virtio-scsi-device>" } ], - "id": "libvirt-9" + "id": "libvirt-10" } { @@ -27550,11 +27565,11 @@ "arguments": { "typename": "virtio-net-ccw" }, - "id": "libvirt-10" + "id": "libvirt-11" } { - "id": "libvirt-10", + "id": "libvirt-11", "error": { "class": "DeviceNotFound", "desc": "Device 'virtio-net-ccw' not found" @@ -27566,11 +27581,11 @@ "arguments": { "typename": "virtio-scsi-ccw" }, - "id": "libvirt-11" + "id": "libvirt-12" } { - "id": "libvirt-11", + "id": "libvirt-12", "error": { "class": "DeviceNotFound", "desc": "Device 'virtio-scsi-ccw' not found" @@ -27582,7 +27597,7 @@ "arguments": { "typename": "vfio-pci" }, - "id": "libvirt-12" + "id": "libvirt-13" } { @@ -27800,7 +27815,7 @@ "type": "int32" } ], - "id": "libvirt-12" + "id": "libvirt-13" } { @@ -27808,7 +27823,7 @@ "arguments": { "typename": "scsi-hd" }, - "id": "libvirt-13" + "id": "libvirt-14" } { @@ -28009,7 +28024,7 @@ "type": "int32" } ], - "id": "libvirt-13" + "id": "libvirt-14" } { @@ -28017,7 +28032,7 @@ "arguments": { "typename": "ide-hd" }, - "id": "libvirt-14" + "id": "libvirt-15" } { @@ -28168,7 +28183,7 @@ "type": "int32" } ], - "id": "libvirt-14" + "id": "libvirt-15" } { @@ -28176,7 +28191,7 @@ "arguments": { "typename": "PIIX4_PM" }, - "id": "libvirt-15" + "id": "libvirt-16" } { @@ -28299,7 +28314,7 @@ "type": "link<irq>" } ], - "id": "libvirt-15" + "id": "libvirt-16" } { @@ -28307,7 +28322,7 @@ "arguments": { "typename": "usb-redir" }, - "id": "libvirt-16" + "id": "libvirt-17" } { @@ -28363,7 +28378,7 @@ "type": "bool" } ], - "id": "libvirt-16" + "id": "libvirt-17" } { @@ -28371,7 +28386,7 @@ "arguments": { "typename": "usb-storage" }, - "id": "libvirt-17" + "id": "libvirt-18" } { @@ -28486,7 +28501,7 @@ "type": "bool" } ], - "id": "libvirt-17" + "id": "libvirt-18" } { @@ -28494,7 +28509,7 @@ "arguments": { "typename": "kvm-pit" }, - "id": "libvirt-18" + "id": "libvirt-19" } { @@ -28510,7 +28525,7 @@ "type": "LostTickPolicy" } ], - "id": "libvirt-18" + "id": "libvirt-19" } { @@ -28518,7 +28533,7 @@ "arguments": { "typename": "VGA" }, - "id": "libvirt-19" + "id": "libvirt-20" } { @@ -28640,7 +28655,7 @@ "type": "uint32" } ], - "id": "libvirt-19" + "id": "libvirt-20" } { @@ -28648,7 +28663,7 @@ "arguments": { "typename": "vmware-svga" }, - "id": "libvirt-20" + "id": "libvirt-21" } { @@ -28723,7 +28738,7 @@ "type": "uint32" } ], - "id": "libvirt-20" + "id": "libvirt-21" } { @@ -28731,7 +28746,7 @@ "arguments": { "typename": "qxl" }, - "id": "libvirt-21" + "id": "libvirt-22" } { @@ -28871,7 +28886,7 @@ "type": "int32" } ], - "id": "libvirt-21" + "id": "libvirt-22" } { @@ -28879,7 +28894,7 @@ "arguments": { "typename": "virtio-gpu-pci" }, - "id": "libvirt-22" + "id": "libvirt-23" } { @@ -29141,7 +29156,7 @@ "type": "child<virtio-gpu-device>" } ], - "id": "libvirt-22" + "id": "libvirt-23" } { @@ -29149,7 +29164,7 @@ "arguments": { "typename": "virtio-gpu-device" }, - "id": "libvirt-23" + "id": "libvirt-24" } { @@ -29249,7 +29264,7 @@ "type": "size" } ], - "id": "libvirt-23" + "id": "libvirt-24" } { @@ -29257,7 +29272,7 @@ "arguments": { "typename": "ICH9-LPC" }, - "id": "libvirt-24" + "id": "libvirt-25" } { @@ -29515,7 +29530,7 @@ "type": "link<irq>" } ], - "id": "libvirt-24" + "id": "libvirt-25" } { @@ -29523,7 +29538,7 @@ "arguments": { "typename": "virtio-balloon-pci" }, - "id": "libvirt-25" + "id": "libvirt-26" } { @@ -29778,7 +29793,7 @@ "type": "child<virtio-balloon-device>" } ], - "id": "libvirt-25" + "id": "libvirt-26" } { @@ -29786,11 +29801,11 @@ "arguments": { "typename": "virtio-balloon-ccw" }, - "id": "libvirt-26" + "id": "libvirt-27" } { - "id": "libvirt-26", + "id": "libvirt-27", "error": { "class": "DeviceNotFound", "desc": "Device 'virtio-balloon-ccw' not found" @@ -29802,7 +29817,7 @@ "arguments": { "typename": "virtio-balloon-device" }, - "id": "libvirt-27" + "id": "libvirt-28" } { @@ -29906,7 +29921,7 @@ "type": "guest statistics" } ], - "id": "libvirt-27" + "id": "libvirt-28" } { @@ -29914,7 +29929,7 @@ "arguments": { "typename": "intel-iommu" }, - "id": "libvirt-28" + "id": "libvirt-29" } { @@ -29987,7 +30002,7 @@ "type": "bool" } ], - "id": "libvirt-28" + "id": "libvirt-29" } { @@ -29995,7 +30010,7 @@ "arguments": { "typename": "mch" }, - "id": "libvirt-29" + "id": "libvirt-30" } { @@ -30070,7 +30085,7 @@ "type": "uint16" } ], - "id": "libvirt-29" + "id": "libvirt-30" } { @@ -30078,7 +30093,7 @@ "arguments": { "typename": "nvdimm" }, - "id": "libvirt-30" + "id": "libvirt-31" } { @@ -30120,7 +30135,7 @@ "type": "uint64" } ], - "id": "libvirt-30" + "id": "libvirt-31" } { @@ -30128,7 +30143,7 @@ "arguments": { "typename": "pcie-root-port" }, - "id": "libvirt-31" + "id": "libvirt-32" } { @@ -30281,7 +30296,7 @@ "type": "size" } ], - "id": "libvirt-31" + "id": "libvirt-32" } { @@ -30289,7 +30304,7 @@ "arguments": { "typename": "usb-host" }, - "id": "libvirt-32" + "id": "libvirt-33" } { @@ -30385,7 +30400,7 @@ "type": "bool" } ], - "id": "libvirt-32" + "id": "libvirt-33" } { @@ -30393,7 +30408,7 @@ "arguments": { "typename": "vhost-user-fs-device" }, - "id": "libvirt-33" + "id": "libvirt-34" } { @@ -30479,7 +30494,7 @@ "type": "int32" } ], - "id": "libvirt-33" + "id": "libvirt-34" } { @@ -30487,7 +30502,7 @@ "arguments": { "typename": "virtio-mem-pci" }, - "id": "libvirt-34" + "id": "libvirt-35" } { @@ -30748,7 +30763,7 @@ "type": "child<virtio-mem>" } ], - "id": "libvirt-34" + "id": "libvirt-35" } { @@ -30756,7 +30771,7 @@ "arguments": { "typename": "virtio-iommu-pci" }, - "id": "libvirt-35" + "id": "libvirt-36" } { @@ -31000,7 +31015,7 @@ "type": "child<virtio-iommu-device>" } ], - "id": "libvirt-35" + "id": "libvirt-36" } { @@ -31008,7 +31023,7 @@ "arguments": { "typename": "memory-backend-file" }, - "id": "libvirt-36" + "id": "libvirt-37" } { @@ -31102,7 +31117,7 @@ "type": "bool" } ], - "id": "libvirt-36" + "id": "libvirt-37" } { @@ -31110,7 +31125,7 @@ "arguments": { "typename": "memory-backend-memfd" }, - "id": "libvirt-37" + "id": "libvirt-38" } { @@ -31189,7 +31204,7 @@ "type": "int" } ], - "id": "libvirt-37" + "id": "libvirt-38" } { @@ -31197,7 +31212,7 @@ "arguments": { "typename": "max-x86_64-cpu" }, - "id": "libvirt-38" + "id": "libvirt-39" } { @@ -33114,12 +33129,12 @@ "type": "bool" } ], - "id": "libvirt-38" + "id": "libvirt-39" } { "execute": "query-machines", - "id": "libvirt-39" + "id": "libvirt-40" } { @@ -33755,7 +33770,7 @@ "default-ram-id": "pc.ram" } ], - "id": "libvirt-39" + "id": "libvirt-40" } { @@ -33763,7 +33778,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-40" + "id": "libvirt-41" } { @@ -33876,12 +33891,12 @@ "type": "child<container>" } ], - "id": "libvirt-40" + "id": "libvirt-41" } { "execute": "query-cpu-definitions", - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -36263,12 +36278,12 @@ "deprecated": false } ], - "id": "libvirt-41" + "id": "libvirt-42" } { "execute": "query-tpm-models", - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -36276,12 +36291,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-tpm-types", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -36289,12 +36304,12 @@ "passthrough", "emulator" ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-command-line-options", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -37769,12 +37784,12 @@ "option": "drive" } ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-migrate-capabilities", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -37876,16 +37891,16 @@ "capability": "mapped-ram" } ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-sev-capabilities", - "id": "libvirt-46" + "id": "libvirt-47" } { - "id": "libvirt-46", + "id": "libvirt-47", "error": { "class": "GenericError", "desc": "SEV: Failed to open /dev/sev: No such file or directory" @@ -37894,11 +37909,11 @@ { "execute": "query-sgx-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { - "id": "libvirt-47", + "id": "libvirt-48", "error": { "class": "GenericError", "desc": "SGX is not enabled in KVM" @@ -37913,7 +37928,7 @@ "name": "host" } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -38281,7 +38296,7 @@ } } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -38295,7 +38310,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -38663,7 +38678,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -38678,7 +38693,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -39152,7 +39167,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml index b646377dec..dbe015d287 100644 --- a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml @@ -3693,4 +3693,7 @@ <cap name='ipi'/> <cap name='avic'/> </hypervCapabilities> + <ebpf> + <object id='rss' data='Test data'/> + </ebpf> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.replies b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.replies index 96a8a8ed2b..019e2f26d9 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.replies @@ -23660,21 +23660,36 @@ } { - "execute": "query-kvm", + "execute": "request-ebpf", + "arguments": { + "id": "rss" + }, + "id": "libvirt-5" +} + +{ + "return": { + "object": "Test data" + }, "id": "libvirt-5" } +{ + "execute": "query-kvm", + "id": "libvirt-6" +} + { "return": { "enabled": true, "present": true }, - "id": "libvirt-5" + "id": "libvirt-6" } { "execute": "qom-list-types", - "id": "libvirt-6" + "id": "libvirt-7" } { @@ -26404,7 +26419,7 @@ "parent": "x86_64-cpu" } ], - "id": "libvirt-6" + "id": "libvirt-7" } { @@ -26412,7 +26427,7 @@ "arguments": { "typename": "virtio-blk-pci" }, - "id": "libvirt-7" + "id": "libvirt-8" } { @@ -26821,7 +26836,7 @@ "type": "bool" } ], - "id": "libvirt-7" + "id": "libvirt-8" } { @@ -26829,7 +26844,7 @@ "arguments": { "typename": "virtio-net-pci" }, - "id": "libvirt-8" + "id": "libvirt-9" } { @@ -27288,7 +27303,7 @@ "type": "bool" } ], - "id": "libvirt-8" + "id": "libvirt-9" } { @@ -27296,7 +27311,7 @@ "arguments": { "typename": "virtio-scsi-pci" }, - "id": "libvirt-9" + "id": "libvirt-10" } { @@ -27562,7 +27577,7 @@ "type": "child<virtio-scsi-device>" } ], - "id": "libvirt-9" + "id": "libvirt-10" } { @@ -27570,11 +27585,11 @@ "arguments": { "typename": "virtio-net-ccw" }, - "id": "libvirt-10" + "id": "libvirt-11" } { - "id": "libvirt-10", + "id": "libvirt-11", "error": { "class": "DeviceNotFound", "desc": "Device 'virtio-net-ccw' not found" @@ -27586,11 +27601,11 @@ "arguments": { "typename": "virtio-scsi-ccw" }, - "id": "libvirt-11" + "id": "libvirt-12" } { - "id": "libvirt-11", + "id": "libvirt-12", "error": { "class": "DeviceNotFound", "desc": "Device 'virtio-scsi-ccw' not found" @@ -27602,7 +27617,7 @@ "arguments": { "typename": "vfio-pci" }, - "id": "libvirt-12" + "id": "libvirt-13" } { @@ -27830,7 +27845,7 @@ "type": "int32" } ], - "id": "libvirt-12" + "id": "libvirt-13" } { @@ -27838,7 +27853,7 @@ "arguments": { "typename": "scsi-hd" }, - "id": "libvirt-13" + "id": "libvirt-14" } { @@ -28039,7 +28054,7 @@ "type": "int32" } ], - "id": "libvirt-13" + "id": "libvirt-14" } { @@ -28047,7 +28062,7 @@ "arguments": { "typename": "ide-hd" }, - "id": "libvirt-14" + "id": "libvirt-15" } { @@ -28198,7 +28213,7 @@ "type": "int32" } ], - "id": "libvirt-14" + "id": "libvirt-15" } { @@ -28206,7 +28221,7 @@ "arguments": { "typename": "PIIX4_PM" }, - "id": "libvirt-15" + "id": "libvirt-16" } { @@ -28329,7 +28344,7 @@ "type": "link<irq>" } ], - "id": "libvirt-15" + "id": "libvirt-16" } { @@ -28337,7 +28352,7 @@ "arguments": { "typename": "usb-redir" }, - "id": "libvirt-16" + "id": "libvirt-17" } { @@ -28393,7 +28408,7 @@ "type": "bool" } ], - "id": "libvirt-16" + "id": "libvirt-17" } { @@ -28401,7 +28416,7 @@ "arguments": { "typename": "usb-storage" }, - "id": "libvirt-17" + "id": "libvirt-18" } { @@ -28516,7 +28531,7 @@ "type": "bool" } ], - "id": "libvirt-17" + "id": "libvirt-18" } { @@ -28524,7 +28539,7 @@ "arguments": { "typename": "kvm-pit" }, - "id": "libvirt-18" + "id": "libvirt-19" } { @@ -28540,7 +28555,7 @@ "type": "LostTickPolicy" } ], - "id": "libvirt-18" + "id": "libvirt-19" } { @@ -28548,7 +28563,7 @@ "arguments": { "typename": "VGA" }, - "id": "libvirt-19" + "id": "libvirt-20" } { @@ -28670,7 +28685,7 @@ "type": "uint32" } ], - "id": "libvirt-19" + "id": "libvirt-20" } { @@ -28678,7 +28693,7 @@ "arguments": { "typename": "vmware-svga" }, - "id": "libvirt-20" + "id": "libvirt-21" } { @@ -28753,7 +28768,7 @@ "type": "uint32" } ], - "id": "libvirt-20" + "id": "libvirt-21" } { @@ -28761,7 +28776,7 @@ "arguments": { "typename": "qxl" }, - "id": "libvirt-21" + "id": "libvirt-22" } { @@ -28901,7 +28916,7 @@ "type": "int32" } ], - "id": "libvirt-21" + "id": "libvirt-22" } { @@ -28909,7 +28924,7 @@ "arguments": { "typename": "virtio-gpu-pci" }, - "id": "libvirt-22" + "id": "libvirt-23" } { @@ -29176,7 +29191,7 @@ "type": "child<virtio-gpu-device>" } ], - "id": "libvirt-22" + "id": "libvirt-23" } { @@ -29184,7 +29199,7 @@ "arguments": { "typename": "virtio-gpu-device" }, - "id": "libvirt-23" + "id": "libvirt-24" } { @@ -29289,7 +29304,7 @@ "type": "size" } ], - "id": "libvirt-23" + "id": "libvirt-24" } { @@ -29297,7 +29312,7 @@ "arguments": { "typename": "ICH9-LPC" }, - "id": "libvirt-24" + "id": "libvirt-25" } { @@ -29555,7 +29570,7 @@ "type": "link<irq>" } ], - "id": "libvirt-24" + "id": "libvirt-25" } { @@ -29563,7 +29578,7 @@ "arguments": { "typename": "virtio-balloon-pci" }, - "id": "libvirt-25" + "id": "libvirt-26" } { @@ -29818,7 +29833,7 @@ "type": "child<virtio-balloon-device>" } ], - "id": "libvirt-25" + "id": "libvirt-26" } { @@ -29826,11 +29841,11 @@ "arguments": { "typename": "virtio-balloon-ccw" }, - "id": "libvirt-26" + "id": "libvirt-27" } { - "id": "libvirt-26", + "id": "libvirt-27", "error": { "class": "DeviceNotFound", "desc": "Device 'virtio-balloon-ccw' not found" @@ -29842,7 +29857,7 @@ "arguments": { "typename": "virtio-balloon-device" }, - "id": "libvirt-27" + "id": "libvirt-28" } { @@ -29946,7 +29961,7 @@ "type": "guest statistics" } ], - "id": "libvirt-27" + "id": "libvirt-28" } { @@ -29954,7 +29969,7 @@ "arguments": { "typename": "intel-iommu" }, - "id": "libvirt-28" + "id": "libvirt-29" } { @@ -30027,7 +30042,7 @@ "type": "bool" } ], - "id": "libvirt-28" + "id": "libvirt-29" } { @@ -30035,7 +30050,7 @@ "arguments": { "typename": "mch" }, - "id": "libvirt-29" + "id": "libvirt-30" } { @@ -30110,7 +30125,7 @@ "type": "uint16" } ], - "id": "libvirt-29" + "id": "libvirt-30" } { @@ -30118,7 +30133,7 @@ "arguments": { "typename": "nvdimm" }, - "id": "libvirt-30" + "id": "libvirt-31" } { @@ -30160,7 +30175,7 @@ "type": "uint64" } ], - "id": "libvirt-30" + "id": "libvirt-31" } { @@ -30168,7 +30183,7 @@ "arguments": { "typename": "pcie-root-port" }, - "id": "libvirt-31" + "id": "libvirt-32" } { @@ -30321,7 +30336,7 @@ "type": "size" } ], - "id": "libvirt-31" + "id": "libvirt-32" } { @@ -30329,7 +30344,7 @@ "arguments": { "typename": "usb-host" }, - "id": "libvirt-32" + "id": "libvirt-33" } { @@ -30425,7 +30440,7 @@ "type": "bool" } ], - "id": "libvirt-32" + "id": "libvirt-33" } { @@ -30433,7 +30448,7 @@ "arguments": { "typename": "vhost-user-fs-device" }, - "id": "libvirt-33" + "id": "libvirt-34" } { @@ -30519,7 +30534,7 @@ "type": "int32" } ], - "id": "libvirt-33" + "id": "libvirt-34" } { @@ -30527,7 +30542,7 @@ "arguments": { "typename": "virtio-mem-pci" }, - "id": "libvirt-34" + "id": "libvirt-35" } { @@ -30788,7 +30803,7 @@ "type": "child<virtio-mem>" } ], - "id": "libvirt-34" + "id": "libvirt-35" } { @@ -30796,7 +30811,7 @@ "arguments": { "typename": "virtio-iommu-pci" }, - "id": "libvirt-35" + "id": "libvirt-36" } { @@ -31040,7 +31055,7 @@ "type": "child<virtio-iommu-device>" } ], - "id": "libvirt-35" + "id": "libvirt-36" } { @@ -31048,7 +31063,7 @@ "arguments": { "typename": "memory-backend-file" }, - "id": "libvirt-36" + "id": "libvirt-37" } { @@ -31142,7 +31157,7 @@ "type": "bool" } ], - "id": "libvirt-36" + "id": "libvirt-37" } { @@ -31150,7 +31165,7 @@ "arguments": { "typename": "memory-backend-memfd" }, - "id": "libvirt-37" + "id": "libvirt-38" } { @@ -31229,7 +31244,7 @@ "type": "int" } ], - "id": "libvirt-37" + "id": "libvirt-38" } { @@ -31237,7 +31252,7 @@ "arguments": { "typename": "max-x86_64-cpu" }, - "id": "libvirt-38" + "id": "libvirt-39" } { @@ -33282,12 +33297,12 @@ "type": "bool" } ], - "id": "libvirt-38" + "id": "libvirt-39" } { "execute": "query-machines", - "id": "libvirt-39" + "id": "libvirt-40" } { @@ -33943,7 +33958,7 @@ "default-ram-id": "pc.ram" } ], - "id": "libvirt-39" + "id": "libvirt-40" } { @@ -33951,7 +33966,7 @@ "arguments": { "typename": "none-machine" }, - "id": "libvirt-40" + "id": "libvirt-41" } { @@ -34064,12 +34079,12 @@ "type": "child<container>" } ], - "id": "libvirt-40" + "id": "libvirt-41" } { "execute": "query-cpu-definitions", - "id": "libvirt-41" + "id": "libvirt-42" } { @@ -36620,12 +36635,12 @@ "deprecated": false } ], - "id": "libvirt-41" + "id": "libvirt-42" } { "execute": "query-tpm-models", - "id": "libvirt-42" + "id": "libvirt-43" } { @@ -36633,12 +36648,12 @@ "tpm-crb", "tpm-tis" ], - "id": "libvirt-42" + "id": "libvirt-43" } { "execute": "query-tpm-types", - "id": "libvirt-43" + "id": "libvirt-44" } { @@ -36646,12 +36661,12 @@ "passthrough", "emulator" ], - "id": "libvirt-43" + "id": "libvirt-44" } { "execute": "query-command-line-options", - "id": "libvirt-44" + "id": "libvirt-45" } { @@ -38134,12 +38149,12 @@ "option": "drive" } ], - "id": "libvirt-44" + "id": "libvirt-45" } { "execute": "query-migrate-capabilities", - "id": "libvirt-45" + "id": "libvirt-46" } { @@ -38233,16 +38248,16 @@ "capability": "mapped-ram" } ], - "id": "libvirt-45" + "id": "libvirt-46" } { "execute": "query-sev-capabilities", - "id": "libvirt-46" + "id": "libvirt-47" } { - "id": "libvirt-46", + "id": "libvirt-47", "error": { "class": "GenericError", "desc": "SEV is not configured" @@ -38251,11 +38266,11 @@ { "execute": "query-sgx-capabilities", - "id": "libvirt-47" + "id": "libvirt-48" } { - "id": "libvirt-47", + "id": "libvirt-48", "error": { "class": "GenericError", "desc": "SGX is not enabled in KVM" @@ -38270,7 +38285,7 @@ "name": "host" } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -38647,7 +38662,7 @@ } } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -38661,7 +38676,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -39038,7 +39053,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -39053,7 +39068,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { @@ -39540,7 +39555,7 @@ } } }, - "id": "libvirt-50" + "id": "libvirt-51" } { diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml index dc548583a5..b0c16a0440 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml @@ -3955,4 +3955,7 @@ <cap name='ipi'/> <cap name='avic'/> </hypervCapabilities> + <ebpf> + <object id='rss' data='Test data'/> + </ebpf> </qemuCaps> -- 2.45.2

Also, added dependencies for libbpf with bpf option. Signed-off-by: Andrew Melnychenko <andrew@daynix.com> --- libvirt.spec.in | 3 ++ meson.build | 7 ++++ meson_options.txt | 1 + src/qemu/meson.build | 1 + src/qemu/qemu_interface.c | 87 +++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_interface.h | 7 ++++ 6 files changed, 106 insertions(+) diff --git a/libvirt.spec.in b/libvirt.spec.in index 29101e74fe..9a27123487 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -366,6 +366,7 @@ BuildRequires: yajl-devel BuildRequires: sanlock-devel >= 2.4 %endif BuildRequires: libpcap-devel >= 1.5.0 +BuildRequires: libbpf-devel >= 1.1.0 BuildRequires: libnl3-devel BuildRequires: libselinux-devel # For modprobe @@ -1374,6 +1375,7 @@ export SOURCE_DATE_EPOCH=$(stat --printf='%Y' %{_specdir}/libvirt.spec) -Dlibpcap=enabled \ %{?arg_nbdkit} \ %{?arg_nbdkit_config_default} \ + -Dlibbpf=enabled \ -Dlibnl=enabled \ -Daudit=enabled \ -Ddtrace=enabled \ @@ -1444,6 +1446,7 @@ export SOURCE_DATE_EPOCH=$(stat --printf='%Y' %{_specdir}/libvirt.spec) -Dlibiscsi=disabled \ -Dnbdkit=disabled \ -Dnbdkit_config_default=disabled \ + -Dlibbpf=disabled \ -Dlibnl=disabled \ -Dlibpcap=disabled \ -Dlibssh2=disabled \ diff --git a/meson.build b/meson.build index 231470e2ee..0647fc74bf 100644 --- a/meson.build +++ b/meson.build @@ -1025,6 +1025,12 @@ else libkvm_dep = dependency('', required: false) endif +libbpf_version = '1.1.0' +libbpf_dep = dependency('libbpf', version: '>=' + libbpf_version, required: get_option('libbpf')) +if libbpf_dep.found() + conf.set('WITH_BPF', 1) +endif + libiscsi_version = '1.18.0' libiscsi_dep = dependency('libiscsi', version: '>=' + libiscsi_version, required: get_option('libiscsi')) @@ -2339,6 +2345,7 @@ libs_summary = { 'dlopen': dlopen_dep.found(), 'fuse': fuse_dep.found(), 'glusterfs': glusterfs_dep.found(), + 'libbpf': libbpf_dep.found(), 'libiscsi': libiscsi_dep.found(), 'libkvm': libkvm_dep.found(), 'libnbd': libnbd_dep.found(), diff --git a/meson_options.txt b/meson_options.txt index 2d440c63d8..be1582186e 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -51,6 +51,7 @@ option('udev', type: 'feature', value: 'auto', description: 'udev support') option('wireshark_dissector', type: 'feature', value: 'auto', description: 'wireshark support') option('wireshark_plugindir', type: 'string', value: '', description: 'wireshark plugins directory for use when installing wireshark plugin') option('yajl', type: 'feature', value: 'auto', description: 'yajl support') +option('libbpf', type: 'feature', value: 'auto', description: 'qemu libbpf support') # build driver options diff --git a/src/qemu/meson.build b/src/qemu/meson.build index 57356451e4..60e7e02373 100644 --- a/src/qemu/meson.build +++ b/src/qemu/meson.build @@ -99,6 +99,7 @@ if conf.has('WITH_QEMU') access_dep, capng_dep, gnutls_dep, + libbpf_dep, libnbd_dep, libnl_dep, log_dep, diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index c2007c7043..3f141afd26 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -38,6 +38,10 @@ #include <sys/stat.h> #include <fcntl.h> +#ifdef WITH_BPF +# include <bpf/libbpf.h> +#endif + #define VIR_FROM_THIS VIR_FROM_QEMU VIR_LOG_INIT("qemu.qemu_interface"); @@ -432,3 +436,86 @@ qemuInterfaceOpenVhostNet(virDomainObj *vm, virDomainAuditNetDevice(vm->def, net, vhostnet_path, vhostfdSize); return 0; } + +#ifdef WITH_BPF + +int +qemuInterfaceLoadEbpf(const char *ebpfObject, + void **retLibbpfObj, + int *fds, + size_t nfds) +{ + int err = 0; + size_t i = 0; + struct bpf_program *prog; + struct bpf_map *map; + struct bpf_object *obj; + size_t ebpfSize = 0; + g_autofree void *ebpfRawData = NULL; + + ebpfRawData = g_base64_decode(ebpfObject, &ebpfSize); + if (ebpfRawData == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("can't decode the eBPF from base64")); + return -1; + } + + obj = bpf_object__open_mem(ebpfRawData, ebpfSize, NULL); + if (!obj) { + virReportError(errno, "%s", _("can't open eBPF object")); + return -1; + } + + + err = bpf_object__load(obj); + if (err) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("can't load eBPF object")); + return -1; + } + + bpf_object__for_each_program(prog, obj) { + fds[i] = bpf_program__fd(prog); + ++i; + if (i > nfds) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("to much file descriptors in eBPF")); + return -1; + } + } + + bpf_object__for_each_map(map, obj) { + fds[i] = bpf_map__fd(map); + ++i; + if (i > nfds) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("to much file descriptors in eBPF")); + return -1; + } + } + + *retLibbpfObj = obj; + + return i - 1; +} + + +void +qemuInterfaceCloseEbpf(void *libbpfObj) +{ + if (libbpfObj) + bpf_object__close(libbpfObj); +} +#else + +int +qemuInterfaceLoadEbpf(const char *ebpfObject G_GNUC_UNUSED, + void **retLibbpfObj G_GNUC_UNUSED, + int *fds G_GNUC_UNUSED, + size_t nfds G_GNUC_UNUSED) +{ + return -2; +} + +void +qemuInterfaceCloseEbpf(void *libbpfObj G_GNUC_UNUSED) +{ +} + +#endif diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h index aee5f9efb0..8ce86b8769 100644 --- a/src/qemu/qemu_interface.h +++ b/src/qemu/qemu_interface.h @@ -44,3 +44,10 @@ int qemuInterfaceOpenVhostNet(virDomainObj *def, int qemuInterfacePrepareSlirp(virQEMUDriver *driver, virDomainNetDef *net); + +int qemuInterfaceLoadEbpf(const char *ebpfObject, + void **retLibbpfObj, + int *fds, + size_t nfds); + +void qemuInterfaceCloseEbpf(void *libbpfObj); -- 2.45.2

Added new capability ebpf_rss_fds for QEMU. Added logic for loading the "RSS" eBPF program. eBPF file descriptors passed to the QEMU. Signed-off-by: Andrew Melnychenko <andrew@daynix.com> --- src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 60 +++++++++++++++++++ src/qemu/qemu_domain.c | 4 ++ src/qemu/qemu_domain.h | 3 + .../caps_9.0.0_x86_64.xml | 1 + .../caps_9.1.0_x86_64.xml | 1 + 7 files changed, 72 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 2d2603e519..1191f96bec 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -713,6 +713,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "sev-snp-guest", /* QEMU_CAPS_SEV_SNP_GUEST */ "netdev.user", /* QEMU_CAPS_NETDEV_USER */ "acpi-erst", /* QEMU_CAPS_DEVICE_ACPI_ERST */ + "virtio-net.ebpf_rss_fds", /* QEMU_CAPS_VIRTIO_NET_EBPF_RSS_FDS */ ); @@ -1454,6 +1455,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVirtioBlk[] = { static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVirtioNet[] = { { "acpi-index", QEMU_CAPS_ACPI_INDEX, NULL }, { "rss", QEMU_CAPS_VIRTIO_NET_RSS, NULL }, + { "ebpf-rss-fds", QEMU_CAPS_VIRTIO_NET_EBPF_RSS_FDS, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsPCIeRootPort[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 2c53236132..4af5e657e4 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -692,6 +692,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_SEV_SNP_GUEST, /* -object sev-snp-guest */ QEMU_CAPS_NETDEV_USER, /* -netdev user */ QEMU_CAPS_DEVICE_ACPI_ERST, /* -device acpi-erst */ + QEMU_CAPS_VIRTIO_NET_EBPF_RSS_FDS, /* virtio-net ebpf_rss_fds feature */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f15e6bda1e..570bc9d1e6 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3806,6 +3806,25 @@ qemuBuildLegacyNicStr(virDomainNetDef *net) } +static virJSONValue * +qemuBuildEbpfRssArg(virDomainNetDef *net) +{ + qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net); + g_autoptr(virJSONValue) props = NULL; + GSList *n; + + if (!netpriv->ebpfrssfds) + return NULL; + + props = virJSONValueNewArray(); + for (n = netpriv->ebpfrssfds; n; n = n->next) { + virJSONValueArrayAppendString(props, qemuFDPassDirectGetPath(n->data)); + } + + return g_steal_pointer(&props); +} + + virJSONValue * qemuBuildNicDevProps(virDomainDef *def, virDomainNetDef *net, @@ -3820,6 +3839,7 @@ qemuBuildNicDevProps(virDomainDef *def, virTristateSwitch mq = VIR_TRISTATE_SWITCH_ABSENT; unsigned long long vectors = 0; virTristateSwitch failover = VIR_TRISTATE_SWITCH_ABSENT; + g_autoptr(virJSONValue) ebpffds = NULL; switch (net->driver.virtio.txmode) { case VIR_DOMAIN_NET_VIRTIO_TX_MODE_IOTHREAD: @@ -3864,6 +3884,8 @@ qemuBuildNicDevProps(virDomainDef *def, if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_NET, net, qemuCaps))) return NULL; + ebpffds = qemuBuildEbpfRssArg(net); + if (virJSONValueObjectAdd(&props, "S:tx", tx, "T:ioeventfd", net->driver.virtio.ioeventfd, @@ -3888,6 +3910,7 @@ qemuBuildNicDevProps(virDomainDef *def, "T:hash", net->driver.virtio.rss_hash_report, "p:host_mtu", net->mtu, "T:failover", failover, + "A:ebpf-rss-fds", &ebpffds, NULL) < 0) return NULL; } else { @@ -4171,6 +4194,38 @@ qemuBuildWatchdogDevProps(const virDomainDef *def, } +static void +qemuOpenEbpfRssFds(virDomainNetDef *net, + virQEMUCaps *qemuCaps) +{ + const char *ebpfRSSObject = NULL; + int fds[16]; + int nfds = 0; + size_t i = 0; + qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net); + + /* Add ebpf values */ + if (net->driver.virtio.rss == VIR_TRISTATE_SWITCH_ON + && net->driver.virtio.rss_hash_report != VIR_TRISTATE_SWITCH_ON + && virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_EBPF_RSS_FDS)) { + ebpfRSSObject = virQEMUCapsGetEbpf(qemuCaps, "rss"); + nfds = qemuInterfaceLoadEbpf(ebpfRSSObject, &netpriv->libbpfRSSObject, fds, G_N_ELEMENTS(fds)); + + if (nfds <= 0) + return; + + for (i = 0; i < nfds; ++i) { + g_autofree char *name = g_strdup_printf("ebpfrssfd-%s-%zu", net->info.alias, i); + + netpriv->ebpfrssfds = + g_slist_prepend(netpriv->ebpfrssfds, qemuFDPassDirectNew(name, fds + i)); + } + + netpriv->ebpfrssfds = g_slist_reverse(netpriv->ebpfrssfds); + } +} + + static int qemuBuildWatchdogCommandLine(virCommand *cmd, const virDomainDef *def, @@ -8729,6 +8784,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver, g_autoptr(virJSONValue) hostnetprops = NULL; qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net); GSList *n; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); if (qemuDomainValidateActualNetDef(net, qemuCaps) < 0) return -1; @@ -8864,6 +8920,10 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver, qemuFDPassDirectTransferCommand(netpriv->slirpfd, cmd); qemuFDPassTransferCommand(netpriv->vdpafd, cmd); + qemuOpenEbpfRssFds(net, qemuCaps); + for (n = netpriv->ebpfrssfds; n; n = n->next) + qemuFDPassDirectTransferCommand(n->data, cmd); + if (!(hostnetprops = qemuBuildHostNetProps(vm, net))) goto cleanup; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 298f4bfb9e..a73f62fb44 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -38,6 +38,7 @@ #include "qemu_checkpoint.h" #include "qemu_validate.h" #include "qemu_namespace.h" +#include "qemu_interface.h" #include "viralloc.h" #include "virlog.h" #include "virerror.h" @@ -1085,6 +1086,7 @@ qemuDomainNetworkPrivateClearFDs(qemuDomainNetworkPrivate *priv) g_clear_pointer(&priv->vdpafd, qemuFDPassFree); g_slist_free_full(g_steal_pointer(&priv->vhostfds), (GDestroyNotify) qemuFDPassDirectFree); g_slist_free_full(g_steal_pointer(&priv->tapfds), (GDestroyNotify) qemuFDPassDirectFree); + g_slist_free_full(g_steal_pointer(&priv->ebpfrssfds), (GDestroyNotify) qemuFDPassDirectFree); } @@ -1096,6 +1098,8 @@ qemuDomainNetworkPrivateDispose(void *obj G_GNUC_UNUSED) qemuSlirpFree(priv->slirp); qemuDomainNetworkPrivateClearFDs(priv); + + qemuInterfaceCloseEbpf(priv->libbpfRSSObject); } diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index a5092dd7f0..3e0345c29d 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -435,6 +435,9 @@ struct _qemuDomainNetworkPrivate { GSList *tapfds; /* qemuFDPassDirect */ GSList *vhostfds; /* qemuFDPassDirect */ qemuFDPass *vdpafd; + + void *libbpfRSSObject; + GSList *ebpfrssfds; /* qemuFDPassDirect eBPF RSS fds from helper */ }; diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml index dbe015d287..689402b472 100644 --- a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml @@ -207,6 +207,7 @@ <flag name='virtio-sound'/> <flag name='netdev.user'/> <flag name='acpi-erst'/> + <flag name='virtio-net.ebpf_rss_fds'/> <version>9000000</version> <microcodeVersion>43100245</microcodeVersion> <package>v9.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml index b0c16a0440..74cf1db19c 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml @@ -205,6 +205,7 @@ <flag name='virtio-sound'/> <flag name='netdev.user'/> <flag name='acpi-erst'/> + <flag name='virtio-net.ebpf_rss_fds'/> <version>9000050</version> <microcodeVersion>43100246</microcodeVersion> <package>v9.0.0-1388-g80e8f06021-dirty</package> -- 2.45.2

Added net-virtio-rss-bpf to qemuxmlconf's test. Synthetically modified caps-9.0.0 with a reply. Added mock functions for loading eBPF. Signed-off-by: Andrew Melnychenko <andrew@daynix.com> Fixed Tests for 9.1.0 Added tests for SPARK Fixed issue with ident Signed-off-by: Andrew Melnychenko <andrew@daynix.com> --- tests/qemuxml2argvmock.c | 24 ++++++++++ .../net-virtio-rss-bpf.x86_64-latest.args | 37 +++++++++++++++ .../net-virtio-rss-bpf.x86_64-latest.xml | 46 +++++++++++++++++++ tests/qemuxmlconfdata/net-virtio-rss-bpf.xml | 46 +++++++++++++++++++ tests/qemuxmlconftest.c | 5 ++ 5 files changed, 158 insertions(+) create mode 100644 tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/net-virtio-rss-bpf.xml diff --git a/tests/qemuxml2argvmock.c b/tests/qemuxml2argvmock.c index 9cc97199c4..f0dba04a10 100644 --- a/tests/qemuxml2argvmock.c +++ b/tests/qemuxml2argvmock.c @@ -292,3 +292,27 @@ virNetDevSetMTU(const char *ifname G_GNUC_UNUSED, { return 0; } + +int +qemuInterfaceLoadEbpf(__attribute__((unused)) const char *ebpfObject, + __attribute__((unused)) void **retLibbpfObj, int *fds, size_t nfds) +{ + if (g_getenv("QEMU_NET_RSS_EBPF_DISABLED")) + return -1; + + if (nfds >= 4) { + fds[0] = 0x100; + fds[1] = 0x101; + fds[2] = 0x102; + fds[3] = 0x103; + return 4; + } else { + return -1; + } +} + +void +qemuInterfaceCloseEbpf(__attribute__((unused)) void *libbpfObj) +{ + return; +} diff --git a/tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.args b/tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.args new file mode 100644 index 0000000000..b9497e5a73 --- /dev/null +++ b/tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.args @@ -0,0 +1,37 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-m size=219136k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","read-only":false}' \ +-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-storage","id":"ide0-0-0","bootindex":1}' \ +-netdev '{"type":"user","id":"hostnet0"}' \ +-device '{"driver":"virtio-net-pci","rss":true,"ebpf-rss-fds":["256","257","258","259"],"netdev":"hostnet0","id":"net0","mac":"00:11:22:33:44:55","bus":"pci.0","addr":"0x2"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x5"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.xml b/tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.xml new file mode 100644 index 0000000000..198540380c --- /dev/null +++ b/tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.xml @@ -0,0 +1,46 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='virtio'/> + <driver rss='on'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/net-virtio-rss-bpf.xml b/tests/qemuxmlconfdata/net-virtio-rss-bpf.xml new file mode 100644 index 0000000000..198540380c --- /dev/null +++ b/tests/qemuxmlconfdata/net-virtio-rss-bpf.xml @@ -0,0 +1,46 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='virtio'/> + <driver rss='on'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 4fccc06fcd..5441e653d2 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1232,6 +1232,7 @@ mymain(void) g_unsetenv("PIPEWIRE_CORE"); g_unsetenv("PIPEWIRE_REMOTE"); g_unsetenv("PIPEWIRE_RUNTIME_DIR"); + g_unsetenv("QEMU_NET_RSS_EBPF_DISABLED"); DO_TEST_CAPS_LATEST("x86_64-pc-minimal"); DO_TEST_CAPS_LATEST_ABI_UPDATE("x86_64-pc-minimal"); @@ -1780,7 +1781,11 @@ mymain(void) DO_TEST_CAPS_LATEST_FAILURE("net-hostdev-fail"); DO_TEST_CAPS_LATEST("net-vdpa"); DO_TEST_CAPS_LATEST("net-vdpa-multiqueue"); + + g_setenv("QEMU_NET_RSS_EBPF_DISABLED", "1", TRUE); DO_TEST_CAPS_LATEST("net-virtio-rss"); + g_unsetenv("QEMU_NET_RSS_EBPF_DISABLED"); + DO_TEST_CAPS_LATEST("net-virtio-rss-bpf"); DO_TEST_CAPS_LATEST("hostdev-pci-multifunction"); -- 2.45.2

ping On Mon, Jul 29, 2024 at 10:49 PM Andrew Melnychenko <andrew@daynix.com> wrote:
This series of rfc patches adds support for loading the RSS eBPF program and passing it to the QEMU. Comments and suggestions would be useful.
QEMU with vhost may work with RSS through eBPF. To load eBPF, the capabilities required that Libvirt may provide. eBPF program and maps may be unique for particular QEMU and Libvirt retrieves eBPF through qapi. For now, there is only "RSS" eBPF object in QEMU, in the future, there may be another one(g.e. network filters). That's why in Libvirt added logic to load and store any eBPF object that QEMU provides using qapi schema.
One of the reasons why this series of patches is in RFC are tests. To this series of patches, the tests were added. For now, the tests are synthetic, the proper "reply" file should be generated with a new "caps" file. Currently, there are changes in caps-9.0.0* and caps-9.1.0 files. There was added support for ebpf_rss_fds feature, and request-ebpf command. So, overall, the tests are required for review, comment, and discussion how we want them to be implemented in the future.
For virtio-net RSS, the document has not changed. ``` <interface type="network"> <model type="virtio"/> <driver queues="4" rss="on" rss_hash_report="off"/> <interface type="network"> ```
Simplified routine for RSS: * Libvirt retrieves eBPF "RSS" and load it. * Libvirt passes file descriptors to virtio-net with property "ebpf_rss_fds" ("rss" property should be "on" too). * if fds was provided - QEMU using eBPF RSS implementation. * if fds was not provided - QEMU tries to load eBPF RSS in own context and use it. * if eBPF RSS was not loaded - QEMU uses "in-qemu" RSS(vhost not supported).
Changes since RFC v3: * changed tests a bit * refactored and rebased * removed "allowEBPF" from qemu config(now env is used for tests)
Changes since RFC v2: * refactored and rebased. * applied changes according to the Qemu. * added basic test.
Changes since RFC v1: * changed eBPF format saved in the XML cache. * refactored and checked with syntax test. * refactored patch hunks.
Andrew Melnychenko (5): qemu_monitor: Added QEMU's "request-ebpf" support. qemu_capabilities: Added logic for retrieving eBPF objects from QEMU. qemu_interface: Added routine for loading the eBPF objects. qemu_command: Added "ebpf_rss_fds" support for virtio-net. tests: Added tests for eBPF blob loading.
libvirt.spec.in | 3 + meson.build | 7 + meson_options.txt | 1 + src/qemu/meson.build | 1 + src/qemu/qemu_capabilities.c | 132 ++++++++++++ src/qemu/qemu_capabilities.h | 5 + src/qemu/qemu_command.c | 60 ++++++ src/qemu/qemu_domain.c | 4 + src/qemu/qemu_domain.h | 3 + src/qemu/qemu_interface.c | 87 ++++++++ src/qemu/qemu_interface.h | 7 + src/qemu/qemu_monitor.c | 9 + src/qemu/qemu_monitor.h | 4 + src/qemu/qemu_monitor_json.c | 27 +++ src/qemu/qemu_monitor_json.h | 4 + .../caps_9.0.0_sparc.replies | 95 +++++---- .../qemucapabilitiesdata/caps_9.0.0_sparc.xml | 3 + .../caps_9.0.0_x86_64.replies | 199 ++++++++++-------- .../caps_9.0.0_x86_64.xml | 4 + .../caps_9.1.0_x86_64.replies | 199 ++++++++++-------- .../caps_9.1.0_x86_64.xml | 4 + tests/qemuxml2argvmock.c | 24 +++ .../net-virtio-rss-bpf.x86_64-latest.args | 37 ++++ .../net-virtio-rss-bpf.x86_64-latest.xml | 46 ++++ tests/qemuxmlconfdata/net-virtio-rss-bpf.xml | 46 ++++ tests/qemuxmlconftest.c | 5 + 26 files changed, 792 insertions(+), 224 deletions(-) create mode 100644 tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/net-virtio-rss-bpf.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/net-virtio-rss-bpf.xml
-- 2.45.2
participants (2)
-
Andrew Melnychenko
-
Yuri Benditovich