Improve vhost-user-test to properly validate VHOST_USER_GET_SHMEM_CONFIG message handling by directly simulating the message exchange.
The test manually triggers the VHOST_USER_GET_SHMEM_CONFIG message by calling chr_read() with a crafted VhostUserMsg, allowing direct validation of the shmem configuration response handler. Added TestServerShmem structure to track shmem configuration state, including nregions_sent and sizes_sent arrays for comprehensive validation. The test verifies that the response contains the expected number of shared memory regions and their corresponding sizes. Signed-off-by: Albert Esteve <aest...@redhat.com> --- tests/qtest/vhost-user-test.c | 91 +++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 75cb3e44b2..44a5e90b2e 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -88,6 +88,7 @@ typedef enum VhostUserRequest { VHOST_USER_SET_VRING_ENABLE = 18, VHOST_USER_GET_CONFIG = 24, VHOST_USER_SET_CONFIG = 25, + VHOST_USER_GET_SHMEM_CONFIG = 44, VHOST_USER_MAX } VhostUserRequest; @@ -109,6 +110,20 @@ typedef struct VhostUserLog { uint64_t mmap_offset; } VhostUserLog; +#define VIRTIO_MAX_SHMEM_REGIONS 256 + +typedef struct VhostUserShMemConfig { + uint32_t nregions; + uint32_t padding; + uint64_t memory_sizes[VIRTIO_MAX_SHMEM_REGIONS]; +} VhostUserShMemConfig; + +typedef struct TestServerShmem { + bool test_enabled; + uint32_t nregions_sent; + uint64_t sizes_sent[VIRTIO_MAX_SHMEM_REGIONS]; +} TestServerShmem; + typedef struct VhostUserMsg { VhostUserRequest request; @@ -124,6 +139,7 @@ typedef struct VhostUserMsg { struct vhost_vring_addr addr; VhostUserMemory memory; VhostUserLog log; + VhostUserShMemConfig shmem; } payload; } QEMU_PACKED VhostUserMsg; @@ -170,6 +186,7 @@ typedef struct TestServer { bool test_fail; int test_flags; int queues; + TestServerShmem shmem; struct vhost_user_ops *vu_ops; } TestServer; @@ -513,6 +530,31 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) qos_printf("set_vring(%d)=%s\n", msg.payload.state.index, msg.payload.state.num ? "enabled" : "disabled"); break; + + case VHOST_USER_GET_SHMEM_CONFIG: + if (!s->shmem.test_enabled) { + /* Reply with error if shmem feature not enabled */ + msg.flags |= VHOST_USER_REPLY_MASK; + msg.size = sizeof(uint64_t); + msg.payload.u64 = -1; /* Error */ + qemu_chr_fe_write_all(chr, (uint8_t *) &msg, VHOST_USER_HDR_SIZE + msg.size); + } else { + /* Reply with test shmem configuration */ + msg.flags |= VHOST_USER_REPLY_MASK; + msg.size = sizeof(VhostUserShMemConfig); + msg.payload.shmem.nregions = 2; /* Test with 2 regions */ + msg.payload.shmem.padding = 0; + msg.payload.shmem.memory_sizes[0] = 0x100000; /* 1MB */ + msg.payload.shmem.memory_sizes[1] = 0x200000; /* 2MB */ + + /* Record what we're sending for test validation */ + s->shmem.nregions_sent = msg.payload.shmem.nregions; + s->shmem.sizes_sent[0] = msg.payload.shmem.memory_sizes[0]; + s->shmem.sizes_sent[1] = msg.payload.shmem.memory_sizes[1]; + + qemu_chr_fe_write_all(chr, (uint8_t *) &msg, VHOST_USER_HDR_SIZE + msg.size); + } + break; default: qos_printf("vhost-user: un-handled message: %d\n", msg.request); @@ -809,6 +851,22 @@ static void *vhost_user_test_setup_shm(GString *cmd_line, void *arg) return server; } +static void *vhost_user_test_setup_shmem_config(GString *cmd_line, void *arg) +{ + TestServer *server = test_server_new("vhost-user-test", arg); + test_server_listen(server); + + /* Enable shmem testing for this server */ + server->shmem.test_enabled = true; + + append_mem_opts(server, cmd_line, 256, TEST_MEMFD_SHM); + server->vu_ops->append_opts(server, cmd_line, ""); + + g_test_queue_destroy(vhost_user_test_cleanup, server); + + return server; +} + static void test_read_guest_mem(void *obj, void *arg, QGuestAllocator *alloc) { TestServer *server = arg; @@ -1089,6 +1147,33 @@ static struct vhost_user_ops g_vu_net_ops = { .get_protocol_features = vu_net_get_protocol_features, }; +/* Test function for VHOST_USER_GET_SHMEM_CONFIG message */ +static void test_shmem_config(void *obj, void *arg, QGuestAllocator *alloc) +{ + TestServer *s = arg; + + g_assert_true(s->shmem.test_enabled); + + g_mutex_lock(&s->data_mutex); + s->shmem.nregions_sent = 0; + s->shmem.sizes_sent[0] = 0; + s->shmem.sizes_sent[1] = 0; + g_mutex_unlock(&s->data_mutex); + + VhostUserMsg msg = { + .request = VHOST_USER_GET_SHMEM_CONFIG, + .flags = VHOST_USER_VERSION, + .size = 0, + }; + chr_read(s, (uint8_t *) &msg, VHOST_USER_HDR_SIZE); + + g_mutex_lock(&s->data_mutex); + g_assert_cmpint(s->shmem.nregions_sent, ==, 2); + g_assert_cmpint(s->shmem.sizes_sent[0], ==, 0x100000); /* 1MB */ + g_assert_cmpint(s->shmem.sizes_sent[1], ==, 0x200000); /* 2MB */ + g_mutex_unlock(&s->data_mutex); +} + static void register_vhost_user_test(void) { QOSGraphTestOptions opts = { @@ -1136,6 +1221,12 @@ static void register_vhost_user_test(void) qos_add_test("vhost-user/multiqueue", "virtio-net", test_multiqueue, &opts); + + opts.before = vhost_user_test_setup_shmem_config; + opts.edge.extra_device_opts = ""; + qos_add_test("vhost-user/shmem-config", + "virtio-net", + test_shmem_config, &opts); } libqos_init(register_vhost_user_test); -- 2.49.0