The helper called before NIC string creation. EBPF fds passed to the child process. The helper called if qemu supports "ebpf_rss_fds" and returns the helper path. If libvirt can't retrieve fds from the helper, qemu will be launched without "ebpf_rss_fds" virtio-net property. Signed-off-by: Andrew Melnychenko <andrew@xxxxxxxxxx> --- src/qemu/qemu_command.c | 36 +++++++++++++++++++++++++++++++++++- src/qemu/qemu_command.h | 2 ++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 67a396a513..2fffcee609 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3377,11 +3377,14 @@ qemuBuildNicDevStr(virDomainDef *def, virDomainNetDef *net, unsigned int bootindex, size_t vhostfdSize, + char **ebpfRSSfds, + size_t ebpfRSSnfds, virQEMUCaps *qemuCaps) { g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; bool usingVirtio = false; char macaddr[VIR_MAC_STRING_BUFLEN]; + size_t i = 0; if (virDomainNetIsVirtioModel(net)) { if (qemuBuildVirtioDevStr(&buf, "virtio-net", qemuCaps, @@ -3498,6 +3501,15 @@ qemuBuildNicDevStr(virDomainDef *def, if (net->driver.virtio.rss == VIR_TRISTATE_SWITCH_ON) { virBufferAsprintf(&buf, ",rss=%s", virTristateSwitchTypeToString(net->driver.virtio.rss)); + + if (ebpfRSSfds != NULL && ebpfRSSnfds) + { + virBufferAsprintf(&buf, ",ebpf_rss_fds="); + for (i = 0; i < (ebpfRSSnfds - 1); ++i) { + virBufferAsprintf(&buf, "%s:",ebpfRSSfds[i]); + } + virBufferAsprintf(&buf, "%s",ebpfRSSfds[ebpfRSSnfds - 1]); + } } if (net->driver.virtio.rss_hash_report == VIR_TRISTATE_SWITCH_ON) { @@ -8492,6 +8504,9 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver, qemuSlirp *slirp; size_t i; g_autoptr(virJSONValue) hostnetprops = NULL; + char **ebpfRSSfdsName = NULL; + int ebpfRSSfds[16] = {}; + int ebpfRSSnfds = 0; if (!bootindex) @@ -8744,8 +8759,20 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver, if (qemuCommandAddExtDevice(cmd, &net->info) < 0) goto cleanup; + if (net->driver.virtio.rss == VIR_TRISTATE_SWITCH_ON + && virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_EBPF_RSS_FDS)) { + ebpfRSSnfds = qemuEbpfRssHelper(virQEMUCapsGetEBPFHelperPath(qemuCaps), ebpfRSSfds, 16); + if (ebpfRSSnfds > 0) { + ebpfRSSfdsName = g_new0(char *, ebpfRSSnfds); + for (i = 0; i < ebpfRSSnfds; ++i) { + ebpfRSSfdsName[i] = g_strdup_printf("%d", ebpfRSSfds[i]); + virCommandPassFD(cmd, ebpfRSSfds[i], VIR_COMMAND_PASS_FD_CLOSE_PARENT); + } + } + } + if (!(nic = qemuBuildNicDevStr(def, net, bootindex, - net->driver.virtio.queues, qemuCaps))) + net->driver.virtio.queues, ebpfRSSfdsName, ebpfRSSnfds, qemuCaps))) goto cleanup; virCommandAddArgList(cmd, "-device", nic, NULL); } else if (!requireNicdev) { @@ -8785,6 +8812,13 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver, } VIR_FREE(tapfdName); VIR_FREE(vhostfd); + for (i = 0; ret < 0 && ebpfRSSfds[i] && i < 16; i++) { + if (ret < 0) + VIR_FORCE_CLOSE(ebpfRSSfds[i]); + if (ebpfRSSfdsName) + VIR_FREE(ebpfRSSfdsName[i]); + } + VIR_FREE(ebpfRSSfdsName); VIR_FREE(tapfd); VIR_FORCE_CLOSE(vdpafd); return ret; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 188e63ea1f..cab0bb7770 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -107,6 +107,8 @@ char *qemuBuildNicDevStr(virDomainDef *def, virDomainNetDef *net, unsigned int bootindex, size_t vhostfdSize, + char **ebpf_rss_fds, + size_t nfds, virQEMUCaps *qemuCaps); char *qemuDeviceDriveHostAlias(virDomainDiskDef *disk); -- 2.31.1