Message ID | 0c6d743253400594ad567d4f255ff30a80c62c4e.1566576129.git.crobinso@redhat.com |
---|---|
State | New |
Headers | show |
Series | Add vhost-user-gpu support | expand |
On 8/23/19 12:21 PM, Cole Robinson wrote: > From: Marc-André Lureau <marcandre.lureau@redhat.com> > > Add qemuVhostUserFetchConfigs() to discover vhost-user helpers. > > qemuVhostUserFillDomainGPU() will find the first matching GPU helper > with the required capabilities and set the associated > vhost_user_binary. > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> > Signed-off-by: Cole Robinson <crobinso@redhat.com> > --- > src/conf/device_conf.c | 1 + > src/conf/device_conf.h | 1 + > src/qemu/Makefile.inc.am | 2 + > src/qemu/qemu_vhost_user.c | 394 ++++++++++++++++++ > src/qemu/qemu_vhost_user.h | 48 +++ > tests/Makefile.am | 9 + > .../etc/qemu/vhost-user/40-gpu.json | 1 + > .../etc/qemu/vhost-user/50-gpu.json | 0 > .../qemu/vhost-user/test-vhost-user-gpu | 11 + > .../usr/share/qemu/vhost-user/30-gpu.json | 1 + > .../usr/share/qemu/vhost-user/50-gpu.json | 8 + > .../usr/share/qemu/vhost-user/60-gpu.json | 1 + > tests/qemuvhostusertest.c | 132 ++++++ > 13 files changed, 609 insertions(+) > create mode 100644 src/qemu/qemu_vhost_user.c > create mode 100644 src/qemu/qemu_vhost_user.h > create mode 120000 tests/qemuvhostuserdata/etc/qemu/vhost-user/40-gpu.json > create mode 100644 tests/qemuvhostuserdata/etc/qemu/vhost-user/50-gpu.json > create mode 100755 tests/qemuvhostuserdata/usr/libexec/qemu/vhost-user/test-vhost-user-gpu > create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/30-gpu.json > create mode 100644 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-gpu.json > create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/60-gpu.json > create mode 100644 tests/qemuvhostusertest.c > > diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c > index 4c57f0995f..2f7077ddc4 100644 > --- a/src/conf/device_conf.c > +++ b/src/conf/device_conf.c > @@ -96,6 +96,7 @@ virDomainDeviceInfoClear(virDomainDeviceInfoPtr info) > VIR_FREE(info->loadparm); > info->isolationGroup = 0; > info->isolationGroupLocked = false; > + VIR_FREE(info->vhost_user_binary); > } > > void > diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h > index d0854925e3..0b0c525ad8 100644 > --- a/src/conf/device_conf.h > +++ b/src/conf/device_conf.h > @@ -179,6 +179,7 @@ struct _virDomainDeviceInfo { > * cases we might want to prevent that from happening by > * locking the isolation group */ > bool isolationGroupLocked; > + char *vhost_user_binary; > }; > > void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); > diff --git a/src/qemu/Makefile.inc.am b/src/qemu/Makefile.inc.am > index f7a0fa4a84..18a9220d01 100644 > --- a/src/qemu/Makefile.inc.am > +++ b/src/qemu/Makefile.inc.am > @@ -60,6 +60,8 @@ QEMU_DRIVER_SOURCES = \ > qemu/qemu_qapi.h \ > qemu/qemu_tpm.c \ > qemu/qemu_tpm.h \ > + qemu/qemu_vhost_user.c \ > + qemu/qemu_vhost_user.h \ > $(NULL) > > > diff --git a/src/qemu/qemu_vhost_user.c b/src/qemu/qemu_vhost_user.c > new file mode 100644 > index 0000000000..7a97052ab9 > --- /dev/null > +++ b/src/qemu/qemu_vhost_user.c > @@ -0,0 +1,394 @@ > +/* > + * qemu_vhost_user.c: QEMU vhost-user > + * > + * Copyright (C) 2019 Red Hat, Inc. > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library. If not, see > + * <http://www.gnu.org/licenses/>. > + */ > + > +#include <config.h> > + > +#include "qemu_vhost_user.h" > +#include "qemu_configs.h" > +#include "virjson.h" > +#include "virlog.h" > +#include "virstring.h" > +#include "viralloc.h" > +#include "virenum.h" > + > +#define VIR_FROM_THIS VIR_FROM_QEMU > + > +VIR_LOG_INIT("qemu.qemu_vhost_user"); > + > +typedef enum { > + QEMU_VHOST_USER_TYPE_NONE = 0, > + QEMU_VHOST_USER_TYPE_9P, > + QEMU_VHOST_USER_TYPE_BALLOON, > + QEMU_VHOST_USER_TYPE_BLOCK, > + QEMU_VHOST_USER_TYPE_CAIF, > + QEMU_VHOST_USER_TYPE_CONSOLE, > + QEMU_VHOST_USER_TYPE_CRYPTO, > + QEMU_VHOST_USER_TYPE_GPU, > + QEMU_VHOST_USER_TYPE_INPUT, > + QEMU_VHOST_USER_TYPE_NET, > + QEMU_VHOST_USER_TYPE_RNG, > + QEMU_VHOST_USER_TYPE_RPMSG, > + QEMU_VHOST_USER_TYPE_RPROC_SERIAL, > + QEMU_VHOST_USER_TYPE_SCSI, > + QEMU_VHOST_USER_TYPE_VSOCK, > + > + QEMU_VHOST_USER_TYPE_LAST > +} qemuVhostUserType; > + > +VIR_ENUM_DECL(qemuVhostUserType); > +VIR_ENUM_IMPL(qemuVhostUserType, > + QEMU_VHOST_USER_TYPE_LAST, > + "", > + "9p", > + "balloon", > + "block", > + "caif", > + "console", > + "crypto", > + "gpu", > + "input", > + "net", > + "rng", > + "rpmsg", > + "rproc-serial", > + "scsi", > + "vsock", > +); > + > +typedef enum { > + QEMU_VHOST_USER_GPU_FEATURE_NONE = 0, > + QEMU_VHOST_USER_GPU_FEATURE_VIRGL, > + QEMU_VHOST_USER_GPU_FEATURE_RENDER_NODE, > + > + QEMU_VHOST_USER_GPU_FEATURE_LAST > +} qemuVhostUserGPUFeature; > + > +VIR_ENUM_DECL(qemuVhostUserGPUFeature); > +VIR_ENUM_IMPL(qemuVhostUserGPUFeature, > + QEMU_VHOST_USER_GPU_FEATURE_LAST, > + "", > + "virgl", > + "render-node", > +); > + > +typedef struct _qemuVhostUserGPU qemuVhostUserGPU; > +typedef qemuVhostUserGPU *qemuVhostUserGPUPtr; > +struct _qemuVhostUserGPU { > + size_t nfeatures; > + qemuVhostUserGPUFeature *features; > +}; > + > +struct _qemuVhostUser { > + /* Description intentionally not parsed. */ > + qemuVhostUserType type; > + char *binary; > + /* Tags intentionally not parsed. */ > + > + union { > + qemuVhostUserGPU gpu; > + } capabilities; > +}; > + > +static void > +qemuVhostUserGPUFeatureFree(qemuVhostUserGPUFeature *features) > +{ > + VIR_FREE(features); > +} > + > + Inconsistent double newline spacing here. But double newline seems to be more common for new code so I suggest standardizing on that. > +VIR_DEFINE_AUTOPTR_FUNC(qemuVhostUserGPUFeature, qemuVhostUserGPUFeatureFree); > + > +void > +qemuVhostUserFree(qemuVhostUserPtr vu) > +{ > + if (!vu) > + return; > + > + if (vu->type == QEMU_VHOST_USER_TYPE_GPU) > + VIR_FREE(vu->capabilities.gpu.features); > + > + VIR_FREE(vu->binary); > + > + VIR_FREE(vu); > +} > + > +/* 1MiB should be enough for everybody (TM) */ > +#define DOCUMENT_SIZE (1024 * 1024) > + Since this is identical to qemu_firmware.c, maybe give it a proper name and move it to the shared file? Otherwise this and the preceding uncommented patches look okay to me, the behavior here largely mirrors qemu_firmware.c - Cole -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
On Fri, Aug 23, 2019 at 12:21:53PM -0400, Cole Robinson wrote: >From: Marc-André Lureau <marcandre.lureau@redhat.com> > >Add qemuVhostUserFetchConfigs() to discover vhost-user helpers. > >qemuVhostUserFillDomainGPU() will find the first matching GPU helper >with the required capabilities and set the associated >vhost_user_binary. > Looks good, but it seems like something we might want to start caching over time, especially if more than one helper per domain will be needed. >Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> >Signed-off-by: Cole Robinson <crobinso@redhat.com> >--- > src/conf/device_conf.c | 1 + > src/conf/device_conf.h | 1 + > src/qemu/Makefile.inc.am | 2 + > src/qemu/qemu_vhost_user.c | 394 ++++++++++++++++++ > src/qemu/qemu_vhost_user.h | 48 +++ > tests/Makefile.am | 9 + > .../etc/qemu/vhost-user/40-gpu.json | 1 + > .../etc/qemu/vhost-user/50-gpu.json | 0 > .../qemu/vhost-user/test-vhost-user-gpu | 11 + > .../usr/share/qemu/vhost-user/30-gpu.json | 1 + > .../usr/share/qemu/vhost-user/50-gpu.json | 8 + > .../usr/share/qemu/vhost-user/60-gpu.json | 1 + > tests/qemuvhostusertest.c | 132 ++++++ > 13 files changed, 609 insertions(+) > create mode 100644 src/qemu/qemu_vhost_user.c > create mode 100644 src/qemu/qemu_vhost_user.h > create mode 120000 tests/qemuvhostuserdata/etc/qemu/vhost-user/40-gpu.json > create mode 100644 tests/qemuvhostuserdata/etc/qemu/vhost-user/50-gpu.json > create mode 100755 tests/qemuvhostuserdata/usr/libexec/qemu/vhost-user/test-vhost-user-gpu > create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/30-gpu.json > create mode 100644 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-gpu.json > create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/60-gpu.json > create mode 100644 tests/qemuvhostusertest.c > >diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c >index 4c57f0995f..2f7077ddc4 100644 >--- a/src/conf/device_conf.c >+++ b/src/conf/device_conf.c >@@ -96,6 +96,7 @@ virDomainDeviceInfoClear(virDomainDeviceInfoPtr info) > VIR_FREE(info->loadparm); > info->isolationGroup = 0; > info->isolationGroupLocked = false; >+ VIR_FREE(info->vhost_user_binary); > } > > void >diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h >index d0854925e3..0b0c525ad8 100644 >--- a/src/conf/device_conf.h >+++ b/src/conf/device_conf.h >@@ -179,6 +179,7 @@ struct _virDomainDeviceInfo { > * cases we might want to prevent that from happening by > * locking the isolation group */ > bool isolationGroupLocked; >+ char *vhost_user_binary; > }; > Not sure about the placement in DeviceInfo, looks more fit for 'driver' to me. Jano -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Hi On Tue, Aug 27, 2019 at 12:30 AM Cole Robinson <crobinso@redhat.com> wrote: > > On 8/23/19 12:21 PM, Cole Robinson wrote: > > From: Marc-André Lureau <marcandre.lureau@redhat.com> > > > > Add qemuVhostUserFetchConfigs() to discover vhost-user helpers. > > > > qemuVhostUserFillDomainGPU() will find the first matching GPU helper > > with the required capabilities and set the associated > > vhost_user_binary. > > > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> > > Signed-off-by: Cole Robinson <crobinso@redhat.com> > > --- > > src/conf/device_conf.c | 1 + > > src/conf/device_conf.h | 1 + > > src/qemu/Makefile.inc.am | 2 + > > src/qemu/qemu_vhost_user.c | 394 ++++++++++++++++++ > > src/qemu/qemu_vhost_user.h | 48 +++ > > tests/Makefile.am | 9 + > > .../etc/qemu/vhost-user/40-gpu.json | 1 + > > .../etc/qemu/vhost-user/50-gpu.json | 0 > > .../qemu/vhost-user/test-vhost-user-gpu | 11 + > > .../usr/share/qemu/vhost-user/30-gpu.json | 1 + > > .../usr/share/qemu/vhost-user/50-gpu.json | 8 + > > .../usr/share/qemu/vhost-user/60-gpu.json | 1 + > > tests/qemuvhostusertest.c | 132 ++++++ > > 13 files changed, 609 insertions(+) > > create mode 100644 src/qemu/qemu_vhost_user.c > > create mode 100644 src/qemu/qemu_vhost_user.h > > create mode 120000 tests/qemuvhostuserdata/etc/qemu/vhost-user/40-gpu.json > > create mode 100644 tests/qemuvhostuserdata/etc/qemu/vhost-user/50-gpu.json > > create mode 100755 tests/qemuvhostuserdata/usr/libexec/qemu/vhost-user/test-vhost-user-gpu > > create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/30-gpu.json > > create mode 100644 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-gpu.json > > create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/60-gpu.json > > create mode 100644 tests/qemuvhostusertest.c > > > > diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c > > index 4c57f0995f..2f7077ddc4 100644 > > --- a/src/conf/device_conf.c > > +++ b/src/conf/device_conf.c > > @@ -96,6 +96,7 @@ virDomainDeviceInfoClear(virDomainDeviceInfoPtr info) > > VIR_FREE(info->loadparm); > > info->isolationGroup = 0; > > info->isolationGroupLocked = false; > > + VIR_FREE(info->vhost_user_binary); > > } > > > > void > > diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h > > index d0854925e3..0b0c525ad8 100644 > > --- a/src/conf/device_conf.h > > +++ b/src/conf/device_conf.h > > @@ -179,6 +179,7 @@ struct _virDomainDeviceInfo { > > * cases we might want to prevent that from happening by > > * locking the isolation group */ > > bool isolationGroupLocked; > > + char *vhost_user_binary; > > }; > > > > void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); > > diff --git a/src/qemu/Makefile.inc.am b/src/qemu/Makefile.inc.am > > index f7a0fa4a84..18a9220d01 100644 > > --- a/src/qemu/Makefile.inc.am > > +++ b/src/qemu/Makefile.inc.am > > @@ -60,6 +60,8 @@ QEMU_DRIVER_SOURCES = \ > > qemu/qemu_qapi.h \ > > qemu/qemu_tpm.c \ > > qemu/qemu_tpm.h \ > > + qemu/qemu_vhost_user.c \ > > + qemu/qemu_vhost_user.h \ > > $(NULL) > > > > > > diff --git a/src/qemu/qemu_vhost_user.c b/src/qemu/qemu_vhost_user.c > > new file mode 100644 > > index 0000000000..7a97052ab9 > > --- /dev/null > > +++ b/src/qemu/qemu_vhost_user.c > > @@ -0,0 +1,394 @@ > > +/* > > + * qemu_vhost_user.c: QEMU vhost-user > > + * > > + * Copyright (C) 2019 Red Hat, Inc. > > + * > > + * This library is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU Lesser General Public > > + * License as published by the Free Software Foundation; either > > + * version 2.1 of the License, or (at your option) any later version. > > + * > > + * This library is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + * Lesser General Public License for more details. > > + * > > + * You should have received a copy of the GNU Lesser General Public > > + * License along with this library. If not, see > > + * <http://www.gnu.org/licenses/>. > > + */ > > + > > +#include <config.h> > > + > > +#include "qemu_vhost_user.h" > > +#include "qemu_configs.h" > > +#include "virjson.h" > > +#include "virlog.h" > > +#include "virstring.h" > > +#include "viralloc.h" > > +#include "virenum.h" > > + > > +#define VIR_FROM_THIS VIR_FROM_QEMU > > + > > +VIR_LOG_INIT("qemu.qemu_vhost_user"); > > + > > +typedef enum { > > + QEMU_VHOST_USER_TYPE_NONE = 0, > > + QEMU_VHOST_USER_TYPE_9P, > > + QEMU_VHOST_USER_TYPE_BALLOON, > > + QEMU_VHOST_USER_TYPE_BLOCK, > > + QEMU_VHOST_USER_TYPE_CAIF, > > + QEMU_VHOST_USER_TYPE_CONSOLE, > > + QEMU_VHOST_USER_TYPE_CRYPTO, > > + QEMU_VHOST_USER_TYPE_GPU, > > + QEMU_VHOST_USER_TYPE_INPUT, > > + QEMU_VHOST_USER_TYPE_NET, > > + QEMU_VHOST_USER_TYPE_RNG, > > + QEMU_VHOST_USER_TYPE_RPMSG, > > + QEMU_VHOST_USER_TYPE_RPROC_SERIAL, > > + QEMU_VHOST_USER_TYPE_SCSI, > > + QEMU_VHOST_USER_TYPE_VSOCK, > > + > > + QEMU_VHOST_USER_TYPE_LAST > > +} qemuVhostUserType; > > + > > +VIR_ENUM_DECL(qemuVhostUserType); > > +VIR_ENUM_IMPL(qemuVhostUserType, > > + QEMU_VHOST_USER_TYPE_LAST, > > + "", > > + "9p", > > + "balloon", > > + "block", > > + "caif", > > + "console", > > + "crypto", > > + "gpu", > > + "input", > > + "net", > > + "rng", > > + "rpmsg", > > + "rproc-serial", > > + "scsi", > > + "vsock", > > +); > > + > > +typedef enum { > > + QEMU_VHOST_USER_GPU_FEATURE_NONE = 0, > > + QEMU_VHOST_USER_GPU_FEATURE_VIRGL, > > + QEMU_VHOST_USER_GPU_FEATURE_RENDER_NODE, > > + > > + QEMU_VHOST_USER_GPU_FEATURE_LAST > > +} qemuVhostUserGPUFeature; > > + > > +VIR_ENUM_DECL(qemuVhostUserGPUFeature); > > +VIR_ENUM_IMPL(qemuVhostUserGPUFeature, > > + QEMU_VHOST_USER_GPU_FEATURE_LAST, > > + "", > > + "virgl", > > + "render-node", > > +); > > + > > +typedef struct _qemuVhostUserGPU qemuVhostUserGPU; > > +typedef qemuVhostUserGPU *qemuVhostUserGPUPtr; > > +struct _qemuVhostUserGPU { > > + size_t nfeatures; > > + qemuVhostUserGPUFeature *features; > > +}; > > + > > +struct _qemuVhostUser { > > + /* Description intentionally not parsed. */ > > + qemuVhostUserType type; > > + char *binary; > > + /* Tags intentionally not parsed. */ > > + > > + union { > > + qemuVhostUserGPU gpu; > > + } capabilities; > > +}; > > + > > +static void > > +qemuVhostUserGPUFeatureFree(qemuVhostUserGPUFeature *features) > > +{ > > + VIR_FREE(features); > > +} > > + > > + > > Inconsistent double newline spacing here. But double newline seems to be > more common for new code so I suggest standardizing on that. ok > > > +VIR_DEFINE_AUTOPTR_FUNC(qemuVhostUserGPUFeature, qemuVhostUserGPUFeatureFree); > > + > > +void > > +qemuVhostUserFree(qemuVhostUserPtr vu) > > +{ > > + if (!vu) > > + return; > > + > > + if (vu->type == QEMU_VHOST_USER_TYPE_GPU) > > + VIR_FREE(vu->capabilities.gpu.features); > > + > > + VIR_FREE(vu->binary); > > + > > + VIR_FREE(vu); > > +} > > + > > +/* 1MiB should be enough for everybody (TM) */ > > +#define DOCUMENT_SIZE (1024 * 1024) > > + > > Since this is identical to qemu_firmware.c, maybe give it a proper name > and move it to the shared file? QEMU_INTEROP_DOCUMENT_SIZE ? (not sure it's really worth it, I am not changing it yet) > > Otherwise this and the preceding uncommented patches look okay to me, > the behavior here largely mirrors qemu_firmware.c thanks > > - Cole > > -- > libvir-list mailing list > libvir-list@redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list
Hi On Tue, Aug 27, 2019 at 12:29 PM Ján Tomko <jtomko@redhat.com> wrote: > > On Fri, Aug 23, 2019 at 12:21:53PM -0400, Cole Robinson wrote: > >From: Marc-André Lureau <marcandre.lureau@redhat.com> > > > >Add qemuVhostUserFetchConfigs() to discover vhost-user helpers. > > > >qemuVhostUserFillDomainGPU() will find the first matching GPU helper > >with the required capabilities and set the associated > >vhost_user_binary. > > > > Looks good, but it seems like something we might want to start caching > over time, especially if more than one helper per domain will be needed. > > >Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> > >Signed-off-by: Cole Robinson <crobinso@redhat.com> > >--- > > src/conf/device_conf.c | 1 + > > src/conf/device_conf.h | 1 + > > src/qemu/Makefile.inc.am | 2 + > > src/qemu/qemu_vhost_user.c | 394 ++++++++++++++++++ > > src/qemu/qemu_vhost_user.h | 48 +++ > > tests/Makefile.am | 9 + > > .../etc/qemu/vhost-user/40-gpu.json | 1 + > > .../etc/qemu/vhost-user/50-gpu.json | 0 > > .../qemu/vhost-user/test-vhost-user-gpu | 11 + > > .../usr/share/qemu/vhost-user/30-gpu.json | 1 + > > .../usr/share/qemu/vhost-user/50-gpu.json | 8 + > > .../usr/share/qemu/vhost-user/60-gpu.json | 1 + > > tests/qemuvhostusertest.c | 132 ++++++ > > 13 files changed, 609 insertions(+) > > create mode 100644 src/qemu/qemu_vhost_user.c > > create mode 100644 src/qemu/qemu_vhost_user.h > > create mode 120000 tests/qemuvhostuserdata/etc/qemu/vhost-user/40-gpu.json > > create mode 100644 tests/qemuvhostuserdata/etc/qemu/vhost-user/50-gpu.json > > create mode 100755 tests/qemuvhostuserdata/usr/libexec/qemu/vhost-user/test-vhost-user-gpu > > create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/30-gpu.json > > create mode 100644 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-gpu.json > > create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/60-gpu.json > > create mode 100644 tests/qemuvhostusertest.c > > > >diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c > >index 4c57f0995f..2f7077ddc4 100644 > >--- a/src/conf/device_conf.c > >+++ b/src/conf/device_conf.c > >@@ -96,6 +96,7 @@ virDomainDeviceInfoClear(virDomainDeviceInfoPtr info) > > VIR_FREE(info->loadparm); > > info->isolationGroup = 0; > > info->isolationGroupLocked = false; > >+ VIR_FREE(info->vhost_user_binary); > > } > > > > void > >diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h > >index d0854925e3..0b0c525ad8 100644 > >--- a/src/conf/device_conf.h > >+++ b/src/conf/device_conf.h > >@@ -179,6 +179,7 @@ struct _virDomainDeviceInfo { > > * cases we might want to prevent that from happening by > > * locking the isolation group */ > > bool isolationGroupLocked; > >+ char *vhost_user_binary; > > }; > > > > Not sure about the placement in DeviceInfo, looks more fit for 'driver' > to me. > That wouldn't follow firmware code, but other than that, driver doesn't really fit either since it's a per-domain/device value.
On Fri, Aug 30, 2019 at 04:04:14PM +0400, Marc-André Lureau wrote: >Hi > >On Tue, Aug 27, 2019 at 12:29 PM Ján Tomko <jtomko@redhat.com> wrote: >> >> On Fri, Aug 23, 2019 at 12:21:53PM -0400, Cole Robinson wrote: >> >From: Marc-André Lureau <marcandre.lureau@redhat.com> >> > >> >Add qemuVhostUserFetchConfigs() to discover vhost-user helpers. >> > >> >qemuVhostUserFillDomainGPU() will find the first matching GPU helper >> >with the required capabilities and set the associated >> >vhost_user_binary. >> > >> >> Looks good, but it seems like something we might want to start caching >> over time, especially if more than one helper per domain will be needed. >> >> >Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> >> >Signed-off-by: Cole Robinson <crobinso@redhat.com> >> >--- >> > src/conf/device_conf.c | 1 + >> > src/conf/device_conf.h | 1 + >> > src/qemu/Makefile.inc.am | 2 + >> > src/qemu/qemu_vhost_user.c | 394 ++++++++++++++++++ >> > src/qemu/qemu_vhost_user.h | 48 +++ >> > tests/Makefile.am | 9 + >> > .../etc/qemu/vhost-user/40-gpu.json | 1 + >> > .../etc/qemu/vhost-user/50-gpu.json | 0 >> > .../qemu/vhost-user/test-vhost-user-gpu | 11 + >> > .../usr/share/qemu/vhost-user/30-gpu.json | 1 + >> > .../usr/share/qemu/vhost-user/50-gpu.json | 8 + >> > .../usr/share/qemu/vhost-user/60-gpu.json | 1 + >> > tests/qemuvhostusertest.c | 132 ++++++ >> > 13 files changed, 609 insertions(+) >> > create mode 100644 src/qemu/qemu_vhost_user.c >> > create mode 100644 src/qemu/qemu_vhost_user.h >> > create mode 120000 tests/qemuvhostuserdata/etc/qemu/vhost-user/40-gpu.json >> > create mode 100644 tests/qemuvhostuserdata/etc/qemu/vhost-user/50-gpu.json >> > create mode 100755 tests/qemuvhostuserdata/usr/libexec/qemu/vhost-user/test-vhost-user-gpu >> > create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/30-gpu.json >> > create mode 100644 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-gpu.json >> > create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/60-gpu.json >> > create mode 100644 tests/qemuvhostusertest.c >> > >> >diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c >> >index 4c57f0995f..2f7077ddc4 100644 >> >--- a/src/conf/device_conf.c >> >+++ b/src/conf/device_conf.c >> >@@ -96,6 +96,7 @@ virDomainDeviceInfoClear(virDomainDeviceInfoPtr info) >> > VIR_FREE(info->loadparm); >> > info->isolationGroup = 0; >> > info->isolationGroupLocked = false; >> >+ VIR_FREE(info->vhost_user_binary); >> > } >> > >> > void >> >diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h >> >index d0854925e3..0b0c525ad8 100644 >> >--- a/src/conf/device_conf.h >> >+++ b/src/conf/device_conf.h >> >@@ -179,6 +179,7 @@ struct _virDomainDeviceInfo { >> > * cases we might want to prevent that from happening by >> > * locking the isolation group */ >> > bool isolationGroupLocked; >> >+ char *vhost_user_binary; >> > }; >> > >> >> Not sure about the placement in DeviceInfo, looks more fit for 'driver' >> to me. >> > >That wouldn't follow firmware code, but other than that, driver >doesn't really fit either since it's a per-domain/device value. > virDomainVideoDriverDefPtr driver; is the one I meant. Jano -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c index 4c57f0995f..2f7077ddc4 100644 --- a/src/conf/device_conf.c +++ b/src/conf/device_conf.c @@ -96,6 +96,7 @@ virDomainDeviceInfoClear(virDomainDeviceInfoPtr info) VIR_FREE(info->loadparm); info->isolationGroup = 0; info->isolationGroupLocked = false; + VIR_FREE(info->vhost_user_binary); } void diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index d0854925e3..0b0c525ad8 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -179,6 +179,7 @@ struct _virDomainDeviceInfo { * cases we might want to prevent that from happening by * locking the isolation group */ bool isolationGroupLocked; + char *vhost_user_binary; }; void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); diff --git a/src/qemu/Makefile.inc.am b/src/qemu/Makefile.inc.am index f7a0fa4a84..18a9220d01 100644 --- a/src/qemu/Makefile.inc.am +++ b/src/qemu/Makefile.inc.am @@ -60,6 +60,8 @@ QEMU_DRIVER_SOURCES = \ qemu/qemu_qapi.h \ qemu/qemu_tpm.c \ qemu/qemu_tpm.h \ + qemu/qemu_vhost_user.c \ + qemu/qemu_vhost_user.h \ $(NULL) diff --git a/src/qemu/qemu_vhost_user.c b/src/qemu/qemu_vhost_user.c new file mode 100644 index 0000000000..7a97052ab9 --- /dev/null +++ b/src/qemu/qemu_vhost_user.c @@ -0,0 +1,394 @@ +/* + * qemu_vhost_user.c: QEMU vhost-user + * + * Copyright (C) 2019 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "qemu_vhost_user.h" +#include "qemu_configs.h" +#include "virjson.h" +#include "virlog.h" +#include "virstring.h" +#include "viralloc.h" +#include "virenum.h" + +#define VIR_FROM_THIS VIR_FROM_QEMU + +VIR_LOG_INIT("qemu.qemu_vhost_user"); + +typedef enum { + QEMU_VHOST_USER_TYPE_NONE = 0, + QEMU_VHOST_USER_TYPE_9P, + QEMU_VHOST_USER_TYPE_BALLOON, + QEMU_VHOST_USER_TYPE_BLOCK, + QEMU_VHOST_USER_TYPE_CAIF, + QEMU_VHOST_USER_TYPE_CONSOLE, + QEMU_VHOST_USER_TYPE_CRYPTO, + QEMU_VHOST_USER_TYPE_GPU, + QEMU_VHOST_USER_TYPE_INPUT, + QEMU_VHOST_USER_TYPE_NET, + QEMU_VHOST_USER_TYPE_RNG, + QEMU_VHOST_USER_TYPE_RPMSG, + QEMU_VHOST_USER_TYPE_RPROC_SERIAL, + QEMU_VHOST_USER_TYPE_SCSI, + QEMU_VHOST_USER_TYPE_VSOCK, + + QEMU_VHOST_USER_TYPE_LAST +} qemuVhostUserType; + +VIR_ENUM_DECL(qemuVhostUserType); +VIR_ENUM_IMPL(qemuVhostUserType, + QEMU_VHOST_USER_TYPE_LAST, + "", + "9p", + "balloon", + "block", + "caif", + "console", + "crypto", + "gpu", + "input", + "net", + "rng", + "rpmsg", + "rproc-serial", + "scsi", + "vsock", +); + +typedef enum { + QEMU_VHOST_USER_GPU_FEATURE_NONE = 0, + QEMU_VHOST_USER_GPU_FEATURE_VIRGL, + QEMU_VHOST_USER_GPU_FEATURE_RENDER_NODE, + + QEMU_VHOST_USER_GPU_FEATURE_LAST +} qemuVhostUserGPUFeature; + +VIR_ENUM_DECL(qemuVhostUserGPUFeature); +VIR_ENUM_IMPL(qemuVhostUserGPUFeature, + QEMU_VHOST_USER_GPU_FEATURE_LAST, + "", + "virgl", + "render-node", +); + +typedef struct _qemuVhostUserGPU qemuVhostUserGPU; +typedef qemuVhostUserGPU *qemuVhostUserGPUPtr; +struct _qemuVhostUserGPU { + size_t nfeatures; + qemuVhostUserGPUFeature *features; +}; + +struct _qemuVhostUser { + /* Description intentionally not parsed. */ + qemuVhostUserType type; + char *binary; + /* Tags intentionally not parsed. */ + + union { + qemuVhostUserGPU gpu; + } capabilities; +}; + +static void +qemuVhostUserGPUFeatureFree(qemuVhostUserGPUFeature *features) +{ + VIR_FREE(features); +} + + +VIR_DEFINE_AUTOPTR_FUNC(qemuVhostUserGPUFeature, qemuVhostUserGPUFeatureFree); + +void +qemuVhostUserFree(qemuVhostUserPtr vu) +{ + if (!vu) + return; + + if (vu->type == QEMU_VHOST_USER_TYPE_GPU) + VIR_FREE(vu->capabilities.gpu.features); + + VIR_FREE(vu->binary); + + VIR_FREE(vu); +} + +/* 1MiB should be enough for everybody (TM) */ +#define DOCUMENT_SIZE (1024 * 1024) + +static int +qemuVhostUserTypeParse(const char *path, + virJSONValuePtr doc, + qemuVhostUserPtr vu) +{ + const char *type = virJSONValueObjectGetString(doc, "type"); + int tmp; + + VIR_DEBUG("vhost-user description path '%s' type : %s", + path, type); + + if ((tmp = qemuVhostUserTypeTypeFromString(type)) <= 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown vhost-user type: '%s'"), + type); + return -1; + } + + vu->type = tmp; + + return 0; +} + +static int +qemuVhostUserBinaryParse(const char *path, + virJSONValuePtr doc, + qemuVhostUserPtr vu) +{ + const char *binary = virJSONValueObjectGetString(doc, "binary"); + + VIR_DEBUG("vhost-user description path '%s' binary : %s", + path, binary); + + if (VIR_STRDUP(vu->binary, binary) < 0) + return -1; + + return 0; +} + +qemuVhostUserPtr +qemuVhostUserParse(const char *path) +{ + VIR_AUTOFREE(char *) cont = NULL; + VIR_AUTOPTR(virJSONValue) doc = NULL; + VIR_AUTOPTR(qemuVhostUser) vu = NULL; + qemuVhostUserPtr ret = NULL; + + if (virFileReadAll(path, DOCUMENT_SIZE, &cont) < 0) + return NULL; + + if (!(doc = virJSONValueFromString(cont))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unable to parse json file '%s'"), + path); + return NULL; + } + + if (VIR_ALLOC(vu) < 0) + return NULL; + + if (qemuVhostUserTypeParse(path, doc, vu) < 0) + return NULL; + + if (qemuVhostUserBinaryParse(path, doc, vu) < 0) + return NULL; + + VIR_STEAL_PTR(ret, vu); + return ret; +} + +char * +qemuVhostUserFormat(qemuVhostUserPtr vu) +{ + VIR_AUTOPTR(virJSONValue) doc = NULL; + + if (!vu) + return NULL; + + if (!(doc = virJSONValueNewObject())) + return NULL; + + if (virJSONValueObjectAppendString(doc, "type", + qemuVhostUserTypeTypeToString(vu->type)) < 0) + return NULL; + + if (virJSONValueObjectAppendString(doc, "binary", vu->binary) < 0) + return NULL; + + return virJSONValueToString(doc, true); +} + +int +qemuVhostUserFetchConfigs(char ***configs, + bool privileged) +{ + return qemuFetchConfigs("vhost-user", configs, privileged); +} + +static ssize_t +qemuVhostUserFetchParsedConfigs(bool privileged, + qemuVhostUserPtr **vhostuserRet, + char ***pathsRet) +{ + VIR_AUTOSTRINGLIST paths = NULL; + size_t npaths; + qemuVhostUserPtr *vus = NULL; + size_t i; + + if (qemuVhostUserFetchConfigs(&paths, privileged) < 0) + return -1; + + npaths = virStringListLength((const char **)paths); + + if (VIR_ALLOC_N(vus, npaths) < 0) + return -1; + + for (i = 0; i < npaths; i++) { + if (!(vus[i] = qemuVhostUserParse(paths[i]))) + goto error; + } + + VIR_STEAL_PTR(*vhostuserRet, vus); + if (pathsRet) + VIR_STEAL_PTR(*pathsRet, paths); + return npaths; + + error: + while (i > 0) + qemuVhostUserFree(vus[--i]); + VIR_FREE(vus); + return -1; +} + + +static int +qemuVhostUserGPUFillCapabilities(qemuVhostUserPtr vu, + virJSONValuePtr doc) +{ + qemuVhostUserGPUPtr gpu = &vu->capabilities.gpu; + virJSONValuePtr featuresJSON; + size_t nfeatures; + size_t i; + VIR_AUTOPTR(qemuVhostUserGPUFeature) features = NULL; + + if (!(featuresJSON = virJSONValueObjectGetArray(doc, "features"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to get features from '%s'"), + vu->binary); + return -1; + } + + nfeatures = virJSONValueArraySize(featuresJSON); + if (VIR_ALLOC_N(features, nfeatures) < 0) + return -1; + + for (i = 0; i < nfeatures; i++) { + virJSONValuePtr item = virJSONValueArrayGet(featuresJSON, i); + const char *tmpStr = virJSONValueGetString(item); + int tmp; + + if ((tmp = qemuVhostUserGPUFeatureTypeFromString(tmpStr)) <= 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown feature %s"), + tmpStr); + continue; + } + + features[i] = tmp; + } + + VIR_STEAL_PTR(gpu->features, features); + gpu->nfeatures = nfeatures; + + return 0; +} + + +static bool +qemuVhostUserGPUHasFeature(qemuVhostUserGPUPtr gpu, + qemuVhostUserGPUFeature feature) +{ + size_t i; + + for (i = 0; i < gpu->nfeatures; i++) { + if (gpu->features[i] == feature) + return true; + } + + return false; +} + + +int +qemuVhostUserFillDomainGPU(virQEMUDriverPtr driver, + virDomainVideoDefPtr video) +{ + qemuVhostUserPtr *vus = NULL; + ssize_t nvus = 0; + ssize_t i; + int ret = -1; + + if ((nvus = qemuVhostUserFetchParsedConfigs(driver->privileged, + &vus, NULL)) < 0) + goto end; + + for (i = 0; i < nvus; i++) { + qemuVhostUserPtr vu = vus[i]; + VIR_AUTOPTR(virJSONValue) doc = NULL; + VIR_AUTOFREE(char *) output = NULL; + VIR_AUTOPTR(virCommand) cmd = NULL; + + if (vu->type != QEMU_VHOST_USER_TYPE_GPU) + continue; + + cmd = virCommandNewArgList(vu->binary, "--print-capabilities", NULL); + virCommandSetOutputBuffer(cmd, &output); + if (virCommandRun(cmd, NULL) < 0) + continue; + + if (!(doc = virJSONValueFromString(output))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unable to parse json capabilities '%s'"), + vu->binary); + continue; + } + + if (qemuVhostUserGPUFillCapabilities(vu, doc) < 0) + continue; + + if (video->accel) { + if (video->accel->accel3d && + !qemuVhostUserGPUHasFeature(&vu->capabilities.gpu, + QEMU_VHOST_USER_GPU_FEATURE_VIRGL)) + continue; + + if (video->accel->rendernode && + !qemuVhostUserGPUHasFeature(&vu->capabilities.gpu, + QEMU_VHOST_USER_GPU_FEATURE_RENDER_NODE)) + continue; + } + + VIR_FREE(video->info.vhost_user_binary); + if (VIR_STRDUP(video->info.vhost_user_binary, vu->binary) < 0) + goto end; + + ret = 0; + break; + } + + if (i == nvus) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("Unable to find a satisfying vhost-user-gpu")); + } + + end: + for (i = 0; i < nvus; i++) + qemuVhostUserFree(vus[i]); + VIR_FREE(vus); + return ret; +} diff --git a/src/qemu/qemu_vhost_user.h b/src/qemu/qemu_vhost_user.h new file mode 100644 index 0000000000..76701dd1fa --- /dev/null +++ b/src/qemu/qemu_vhost_user.h @@ -0,0 +1,48 @@ +/* + * qemu_vhost_user.h: QEMU vhost-user + * + * Copyright (C) 2019 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "domain_conf.h" +#include "qemu_conf.h" +#include "virautoclean.h" +#include "virarch.h" + +typedef struct _qemuVhostUser qemuVhostUser; +typedef qemuVhostUser *qemuVhostUserPtr; + +void +qemuVhostUserFree(qemuVhostUserPtr fw); + +VIR_DEFINE_AUTOPTR_FUNC(qemuVhostUser, qemuVhostUserFree); + +qemuVhostUserPtr +qemuVhostUserParse(const char *path); + +char * +qemuVhostUserFormat(qemuVhostUserPtr fw); + +int +qemuVhostUserFetchConfigs(char ***configs, + bool privileged); + +int +qemuVhostUserFillDomainGPU(virQEMUDriverPtr driver, + virDomainVideoDefPtr video); diff --git a/tests/Makefile.am b/tests/Makefile.am index f92710db43..4f4a5236ea 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -290,6 +290,7 @@ test_programs += qemuxml2argvtest qemuxml2xmltest \ qemumigparamstest \ qemusecuritytest \ qemufirmwaretest \ + qemuvhostusertest \ $(NULL) test_helpers += qemucapsprobe test_libraries += libqemumonitortestutils.la \ @@ -692,6 +693,13 @@ qemufirmwaretest_SOURCES = \ $(NULL) qemufirmwaretest_LDADD = $(qemu_LDADDS) +qemuvhostusertest_SOURCES = \ + qemuvhostusertest.c \ + testutils.h testutils.c \ + virfilewrapper.c virfilewrapper.h \ + $(NULL) +qemuvhostusertest_LDADD = $(qemu_LDADDS) + else ! WITH_QEMU EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c \ qemudomaincheckpointxml2xmltest.c qemudomainsnapshotxml2xmltest.c \ @@ -706,6 +714,7 @@ EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c \ qemusecuritytest.c qemusecuritytest.h \ qemusecuritymock.c \ qemufirmwaretest.c \ + qemuvhostusertest.c \ $(QEMUMONITORTESTUTILS_SOURCES) endif ! WITH_QEMU diff --git a/tests/qemuvhostuserdata/etc/qemu/vhost-user/40-gpu.json b/tests/qemuvhostuserdata/etc/qemu/vhost-user/40-gpu.json new file mode 120000 index 0000000000..aa93864aa7 --- /dev/null +++ b/tests/qemuvhostuserdata/etc/qemu/vhost-user/40-gpu.json @@ -0,0 +1 @@ +../../../usr/share/qemu/vhost-user/50-gpu.json \ No newline at end of file diff --git a/tests/qemuvhostuserdata/etc/qemu/vhost-user/50-gpu.json b/tests/qemuvhostuserdata/etc/qemu/vhost-user/50-gpu.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qemuvhostuserdata/usr/libexec/qemu/vhost-user/test-vhost-user-gpu b/tests/qemuvhostuserdata/usr/libexec/qemu/vhost-user/test-vhost-user-gpu new file mode 100755 index 0000000000..a2c2ee0713 --- /dev/null +++ b/tests/qemuvhostuserdata/usr/libexec/qemu/vhost-user/test-vhost-user-gpu @@ -0,0 +1,11 @@ +#!/bin/sh + +cat <<EOF +{ + "type": "gpu", + "features": [ + "render-node", + "virgl" + ] +} +EOF diff --git a/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/30-gpu.json b/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/30-gpu.json new file mode 120000 index 0000000000..7051776593 --- /dev/null +++ b/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/30-gpu.json @@ -0,0 +1 @@ +50-gpu.json \ No newline at end of file diff --git a/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-gpu.json b/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-gpu.json new file mode 100644 index 0000000000..4c751971db --- /dev/null +++ b/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-gpu.json @@ -0,0 +1,8 @@ +{ + "description": "QEMU vhost-user-gpu", + "type": "gpu", + "binary": "/usr/libexec/qemu/vhost-user/test-vhost-user-gpu", + "tags": [ + "CONFIG_OPENGL_DMABUF=y" + ] +} diff --git a/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/60-gpu.json b/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/60-gpu.json new file mode 120000 index 0000000000..7051776593 --- /dev/null +++ b/tests/qemuvhostuserdata/usr/share/qemu/vhost-user/60-gpu.json @@ -0,0 +1 @@ +50-gpu.json \ No newline at end of file diff --git a/tests/qemuvhostusertest.c b/tests/qemuvhostusertest.c new file mode 100644 index 0000000000..52adf9834a --- /dev/null +++ b/tests/qemuvhostusertest.c @@ -0,0 +1,132 @@ +#include <config.h> + +#include <inttypes.h> + +#include "testutils.h" +#include "virfilewrapper.h" +#include "qemu/qemu_vhost_user.h" +#include "configmake.h" + +#define VIR_FROM_THIS VIR_FROM_QEMU + +/* A very basic test. Parse given JSON vhostuser description into + * an internal structure, format it back and compare with the + * contents of the file (minus some keys that are not parsed). + */ +static int +testParseFormatVU(const void *opaque) +{ + const char *filename = opaque; + VIR_AUTOFREE(char *) path = NULL; + VIR_AUTOPTR(qemuVhostUser) vu = NULL; + VIR_AUTOFREE(char *) buf = NULL; + VIR_AUTOPTR(virJSONValue) json = NULL; + VIR_AUTOFREE(char *) expected = NULL; + VIR_AUTOFREE(char *) actual = NULL; + + if (virAsprintf(&path, "%s/qemuvhostuserdata/%s", + abs_srcdir, filename) < 0) + return -1; + + if (!(vu = qemuVhostUserParse(path))) + return -1; + + if (virFileReadAll(path, + 1024 * 1024, /* 1MiB */ + &buf) < 0) + return -1; + + if (!(json = virJSONValueFromString(buf))) + return -1; + + /* Description and tags are not parsed. */ + if (virJSONValueObjectRemoveKey(json, "description", NULL) < 0 || + virJSONValueObjectRemoveKey(json, "tags", NULL) < 0) + return -1; + + if (!(expected = virJSONValueToString(json, true))) + return -1; + + if (!(actual = qemuVhostUserFormat(vu))) + return -1; + + return virTestCompareToString(expected, actual); +} + + +static int +testVUPrecedence(const void *opaque ATTRIBUTE_UNUSED) +{ + VIR_AUTOFREE(char *) fakehome = NULL; + VIR_AUTOSTRINGLIST vuList = NULL; + size_t nvuList; + size_t i; + const char *expected[] = { + PREFIX "/share/qemu/vhost-user/30-gpu.json", + SYSCONFDIR "/qemu/vhost-user/40-gpu.json", + PREFIX "/share/qemu/vhost-user/60-gpu.json", + }; + const size_t nexpected = ARRAY_CARDINALITY(expected); + + if (VIR_STRDUP(fakehome, abs_srcdir "/qemuvhostuserdata/home/user/.config") < 0) + return -1; + + setenv("XDG_CONFIG_HOME", fakehome, 1); + + if (qemuVhostUserFetchConfigs(&vuList, false) < 0) + return -1; + + if (!vuList) { + fprintf(stderr, "Expected a non-NULL result, but got a NULL result\n"); + return -1; + } + + nvuList = virStringListLength((const char **)vuList); + + for (i = 0; i < MAX(nvuList, nexpected); i++) { + const char *e = i < nexpected ? expected[i] : NULL; + const char *f = i < nvuList ? vuList[i] : NULL; + + if (STRNEQ_NULLABLE(e, f)) { + fprintf(stderr, + "Unexpected path (i=%zu). Expected %s got %s \n", + i, NULLSTR(e), NULLSTR(f)); + return -1; + } + } + + return 0; +} + + +static int +mymain(void) +{ + int ret = 0; + + virFileWrapperAddPrefix(SYSCONFDIR "/qemu/vhost-user", + abs_srcdir "/qemuvhostuserdata/etc/qemu/vhost-user"); + virFileWrapperAddPrefix(PREFIX "/share/qemu/vhost-user", + abs_srcdir "/qemuvhostuserdata/usr/share/qemu/vhost-user"); + virFileWrapperAddPrefix("/home/user/.config/qemu/vhost-user", + abs_srcdir "/qemuvhostuserdata/home/user/.config/qemu/vhost-user"); + +#define DO_PARSE_TEST(filename) \ + do { \ + if (virTestRun("QEMU vhost-user " filename, \ + testParseFormatVU, filename) < 0) \ + ret = -1; \ + } while (0) + + DO_PARSE_TEST("usr/share/qemu/vhost-user/50-gpu.json"); + + if (virTestRun("QEMU vhost-user precedence test", testVUPrecedence, NULL) < 0) + ret = -1; + + virFileWrapperClearPrefixes(); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + + +VIR_TEST_MAIN(mymain)