[RFC PATCH 07/10] qemu_interface: Added ebpf helper call.

Michal Prívozník mprivozn at redhat.com
Fri Aug 20 12:57:12 UTC 2021


On 7/28/21 10:17 AM, Andrew Melnychenko wrote:
> New function to call "qemu-ebpf-rss-helper".
> The helper passes few fds through unix socket.
> Technically libvirt should not be aware how many and what those fds.
> The helper should return fds that should be passed to the qemu as is and in same order.
> 
> Signed-off-by: Andrew Melnychenko <andrew at daynix.com>
> ---
>  src/qemu/qemu_interface.c | 54 +++++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_interface.h |  2 ++
>  2 files changed, 56 insertions(+)
> 
> diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
> index ac0168c80d..76435af94e 100644
> --- a/src/qemu/qemu_interface.c
> +++ b/src/qemu/qemu_interface.c
> @@ -777,3 +777,57 @@ qemuInterfaceOpenVhostNet(virDomainDef *def,
>  
>      return -1;
>  }
> +
> +
> +int qemuEbpfRssHelper(const char *helper, int *fds, int nfds)
> +{
> +    int ret = 0;
> +    int err = 0;
> +    int unix_fds[2] = { -1, -1 };
> +    virCommand *cmd = NULL;

If you'd use:

g_autoptr(virCommand) cmd = NULL;

then you can ditch that explicit virCommandFree() call below.


> +
> +    if (!helper || !fds || !nfds) {
> +        return -1;
> +    }
> +
> +    ret = socketpair(AF_UNIX, SOCK_STREAM, 0, unix_fds);
> +    if (ret) {
> +        virReportSystemError(errno, "%s", _("failed to create socket"));
> +        return -1;
> +    }
> +
> +    cmd = virCommandNew(helper);
> +    if (cmd == NULL) {

This can't really happen. Also, all virCommand* APIs are prepared for
this situation so that we can write simpler code:

cmd = virCommandNew();
virCommandSomething(cmd);
virCommandSomethingElse(cmd);
if (virCommandRunAsync(cmd) < 0) /* This is the point where we learn
about any previous error */

> +        VIR_FORCE_CLOSE(unix_fds[1]);
> +        ret = -1;
> +        goto cleanup;
> +    }
> +    virCommandAddArgFormat(cmd, "--fd=%d", unix_fds[1]);
> +    virCommandPassFD(cmd, unix_fds[1], VIR_COMMAND_PASS_FD_CLOSE_PARENT);
> +    virCommandDoAsyncIO(cmd);
> +
> +    if (virCommandRunAsync(cmd, NULL) < 0) {
> +        VIR_FORCE_CLOSE(unix_fds[1]);

This doesn't look right. Even in case of failure virCommandRun* should
have closed all CLOSE_PARENT FDs. So this is effectively a double close.

> +        ret = -1;
> +        goto cleanup;
> +    }
> +
> +    memset(fds, 0, sizeof(*fds) * nfds);
> +
> +    ret = virSocketRecvMultipleFDs(unix_fds[0], fds, nfds, 0);
> +
> +    if (virCommandWait(cmd, &err) < 0) {
> +        int i = 0;
> +        for (; i < ret; ++i) {
> +            if (fds[i]) {

This check seems needless. After successful return from
virSocketRecvMultipleFDs() the @fds array must be filled with only valid
FDs.

> +                VIR_FORCE_CLOSE(fds[i]);
> +            }
> +        }
> +        ret = -1;
> +    }
> +
> +cleanup:
> +    VIR_FORCE_CLOSE(unix_fds[0]);
> +    virCommandFree(cmd);
> +    return ret;
> +}
> diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h
> index 438d548065..63d7590035 100644
> --- a/src/qemu/qemu_interface.h
> +++ b/src/qemu/qemu_interface.h
> @@ -61,3 +61,5 @@ int qemuInterfacePrepareSlirp(virQEMUDriver *driver,
>                                qemuSlirp **slirp);
>  
>  int qemuInterfaceVDPAConnect(virDomainNetDef *net) G_GNUC_NO_INLINE;
> +
> +int qemuEbpfRssHelper(const char *helper, int *fds, int nfds);
> 

Michal




More information about the libvir-list mailing list