From nobody Tue Feb 10 09:54:20 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1717503322; cv=none; d=zohomail.com; s=zohoarc; b=E7FsbqaQikUhxvpQEgumYwFDGVlXTBNnWZ0PpTlpCA2WJCEm0y+GaChHIuqiV91yedQaVJDwDT7fMcoo1DWR6ExVvZqpEtoMdyKxzopCVnvI1KzVQZo0W1eVrqCQQ6N11EJWG/t8oGC7w8wdRLDX221yf7nke8NJ3QrCgFll+mo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1717503322; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=Jlxj5hAUxBLwqzbYblEX9AjeaQKVFRfrKjY/HWHl1vI=; b=Oq8LoKzlAlZldzZiXiPjsuEegzutUrKXlOcwpZ+tBwZf0nQvzZcJwBLJVfrqa22NqOITb0MKzK/5hOhK5+T/jOMKuk1z1RluUHg+WbMLj5Pwb0NPoReHAyOOOoXxW1E+tdZMjNqtu47lGxszfUI0ai+1hHJpnRtWxHTc2KfbT60= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1717503322137687.6484990459834; Tue, 4 Jun 2024 05:15:22 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sET3o-0003i7-9U; Tue, 04 Jun 2024 08:14:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sET3l-0003gL-F5 for qemu-devel@nongnu.org; Tue, 04 Jun 2024 08:14:37 -0400 Received: from szxga03-in.huawei.com ([45.249.212.189]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sET3g-0006wr-3v for qemu-devel@nongnu.org; Tue, 04 Jun 2024 08:14:36 -0400 Received: from mail.maildlp.com (unknown [172.19.163.48]) by szxga03-in.huawei.com (SkyGuard) with ESMTP id 4VtqF55KFlzPpNw; Tue, 4 Jun 2024 20:11:05 +0800 (CST) Received: from dggpemf200006.china.huawei.com (unknown [7.185.36.61]) by mail.maildlp.com (Postfix) with ESMTPS id 20034180060; Tue, 4 Jun 2024 20:14:22 +0800 (CST) Received: from DESKTOP-8LI8G6S.china.huawei.com (10.173.124.235) by dggpemf200006.china.huawei.com (7.185.36.61) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Tue, 4 Jun 2024 20:14:21 +0800 To: CC: , , , , , , , , , , , , , , , Jialin Wang Subject: [PATCH 4/6] tests/unit: add test-io-channel-rdma.c Date: Tue, 4 Jun 2024 20:14:10 +0800 Message-ID: <1717503252-51884-5-git-send-email-arei.gonglei@huawei.com> X-Mailer: git-send-email 2.8.2.windows.1 In-Reply-To: <1717503252-51884-1-git-send-email-arei.gonglei@huawei.com> References: <1717503252-51884-1-git-send-email-arei.gonglei@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.173.124.235] X-ClientProxiedBy: dggems704-chm.china.huawei.com (10.3.19.181) To dggpemf200006.china.huawei.com (7.185.36.61) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=45.249.212.189; envelope-from=arei.gonglei@huawei.com; helo=szxga03-in.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Gonglei From: Gonglei via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1717503323949100003 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Jialin Wang Signed-off-by: Jialin Wang Signed-off-by: Gonglei --- tests/unit/meson.build | 1 + tests/unit/test-io-channel-rdma.c | 276 ++++++++++++++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 tests/unit/test-io-channel-rdma.c diff --git a/tests/unit/meson.build b/tests/unit/meson.build index 26c109c968..c44020a3b5 100644 --- a/tests/unit/meson.build +++ b/tests/unit/meson.build @@ -85,6 +85,7 @@ if have_block 'test-authz-listfile': [authz], 'test-io-task': [testblock], 'test-io-channel-socket': ['socket-helpers.c', 'io-channel-helpers.c',= io], + 'test-io-channel-rdma': ['io-channel-helpers.c', io], 'test-io-channel-file': ['io-channel-helpers.c', io], 'test-io-channel-command': ['io-channel-helpers.c', io], 'test-io-channel-buffer': ['io-channel-helpers.c', io], diff --git a/tests/unit/test-io-channel-rdma.c b/tests/unit/test-io-channel= -rdma.c new file mode 100644 index 0000000000..e96b55c8c7 --- /dev/null +++ b/tests/unit/test-io-channel-rdma.c @@ -0,0 +1,276 @@ +/* + * QEMU I/O channel RDMA test + * + * Copyright (c) 2024 HUAWEI TECHNOLOGIES CO., LTD. + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "io/channel-rdma.h" +#include "qapi/error.h" +#include "qemu/main-loop.h" +#include "qemu/module.h" +#include "io-channel-helpers.h" +#include "qapi-types-sockets.h" +#include + +static SocketAddress *l_addr; +static SocketAddress *c_addr; + +static void test_io_channel_set_rdma_bufs(QIOChannel *src, QIOChannel *dst) +{ + int buflen =3D 64 * 1024; + + /* + * Make the socket buffers small so that we see + * the effects of partial reads/writes + */ + rsetsockopt(((QIOChannelRDMA *)src)->fd, SOL_SOCKET, SO_SNDBUF, + (char *)&buflen, sizeof(buflen)); + + rsetsockopt(((QIOChannelRDMA *)dst)->fd, SOL_SOCKET, SO_SNDBUF, + (char *)&buflen, sizeof(buflen)); +} + +static void test_io_channel_setup_sync(InetSocketAddress *listen_addr, + InetSocketAddress *connect_addr, + QIOChannel **srv, QIOChannel **src, + QIOChannel **dst) +{ + QIOChannelRDMA *lioc; + + lioc =3D qio_channel_rdma_new(); + qio_channel_rdma_listen_sync(lioc, listen_addr, 1, &error_abort); + + *src =3D QIO_CHANNEL(qio_channel_rdma_new()); + qio_channel_rdma_connect_sync(QIO_CHANNEL_RDMA(*src), connect_addr, + &error_abort); + qio_channel_set_delay(*src, false); + + qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN); + *dst =3D QIO_CHANNEL(qio_channel_rdma_accept(lioc, &error_abort)); + g_assert(*dst); + + test_io_channel_set_rdma_bufs(*src, *dst); + + *srv =3D QIO_CHANNEL(lioc); +} + +struct TestIOChannelData { + bool err; + GMainLoop *loop; +}; + +static void test_io_channel_complete(QIOTask *task, gpointer opaque) +{ + struct TestIOChannelData *data =3D opaque; + data->err =3D qio_task_propagate_error(task, NULL); + g_main_loop_quit(data->loop); +} + +static void test_io_channel_setup_async(InetSocketAddress *listen_addr, + InetSocketAddress *connect_addr, + QIOChannel **srv, QIOChannel **src, + QIOChannel **dst) +{ + QIOChannelRDMA *lioc; + struct TestIOChannelData data; + + data.loop =3D g_main_loop_new(g_main_context_default(), TRUE); + + lioc =3D qio_channel_rdma_new(); + qio_channel_rdma_listen_async(lioc, listen_addr, 1, + test_io_channel_complete, &data, NULL, N= ULL); + + g_main_loop_run(data.loop); + g_main_context_iteration(g_main_context_default(), FALSE); + + g_assert(!data.err); + + *src =3D QIO_CHANNEL(qio_channel_rdma_new()); + + qio_channel_rdma_connect_async(QIO_CHANNEL_RDMA(*src), connect_addr, + test_io_channel_complete, &data, NULL, = NULL); + + g_main_loop_run(data.loop); + g_main_context_iteration(g_main_context_default(), FALSE); + + g_assert(!data.err); + + if (qemu_in_coroutine()) { + qio_channel_yield(QIO_CHANNEL(lioc), G_IO_IN); + } else { + qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN); + } + *dst =3D QIO_CHANNEL(qio_channel_rdma_accept(lioc, &error_abort)); + g_assert(*dst); + + qio_channel_set_delay(*src, false); + test_io_channel_set_rdma_bufs(*src, *dst); + + *srv =3D QIO_CHANNEL(lioc); + + g_main_loop_unref(data.loop); +} + +static void test_io_channel(bool async, InetSocketAddress *listen_addr, + InetSocketAddress *connect_addr) +{ + QIOChannel *src, *dst, *srv; + QIOChannelTest *test; + + if (async) { + /* async + blocking */ + + test_io_channel_setup_async(listen_addr, connect_addr, &srv, &src, + &dst); + + g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN= )); + g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN= )); + + test =3D qio_channel_test_new(); + qio_channel_test_run_threads(test, true, src, dst); + qio_channel_test_validate(test); + + /* unref without close, to ensure finalize() cleans up */ + + object_unref(OBJECT(src)); + object_unref(OBJECT(dst)); + object_unref(OBJECT(srv)); + + /* async + non-blocking */ + + test_io_channel_setup_async(listen_addr, connect_addr, &srv, &src, + &dst); + + g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN= )); + g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN= )); + + test =3D qio_channel_test_new(); + qio_channel_test_run_threads(test, false, src, dst); + qio_channel_test_validate(test); + + /* close before unref, to ensure finalize copes with already close= d */ + + qio_channel_close(src, &error_abort); + qio_channel_close(dst, &error_abort); + object_unref(OBJECT(src)); + object_unref(OBJECT(dst)); + + qio_channel_close(srv, &error_abort); + object_unref(OBJECT(srv)); + } else { + /* sync + blocking */ + + test_io_channel_setup_sync(listen_addr, connect_addr, &srv, &src, = &dst); + + g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN= )); + g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN= )); + + test =3D qio_channel_test_new(); + qio_channel_test_run_threads(test, true, src, dst); + qio_channel_test_validate(test); + + /* unref without close, to ensure finalize() cleans up */ + + object_unref(OBJECT(src)); + object_unref(OBJECT(dst)); + object_unref(OBJECT(srv)); + + /* sync + non-blocking */ + + test_io_channel_setup_sync(listen_addr, connect_addr, &srv, &src, = &dst); + + g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN= )); + g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN= )); + + test =3D qio_channel_test_new(); + qio_channel_test_run_threads(test, false, src, dst); + qio_channel_test_validate(test); + + /* close before unref, to ensure finalize copes with already close= d */ + + qio_channel_close(src, &error_abort); + qio_channel_close(dst, &error_abort); + object_unref(OBJECT(src)); + object_unref(OBJECT(dst)); + + qio_channel_close(srv, &error_abort); + object_unref(OBJECT(srv)); + } +} + +static void test_io_channel_rdma(bool async) +{ + InetSocketAddress *listen_addr; + InetSocketAddress *connect_addr; + + listen_addr =3D &l_addr->u.inet; + connect_addr =3D &l_addr->u.inet; + + test_io_channel(async, listen_addr, connect_addr); +} + +static void test_io_channel_rdma_sync(void) +{ + test_io_channel_rdma(false); +} + +static void test_io_channel_rdma_async(void) +{ + test_io_channel_rdma(true); +} + +static void test_io_channel_rdma_co(void *opaque) +{ + test_io_channel_rdma(true); +} + +static void test_io_channel_rdma_coroutine(void) +{ + Coroutine *coroutine; + + coroutine =3D qemu_coroutine_create(test_io_channel_rdma_co, NULL); + qemu_coroutine_enter(coroutine); +} + +int main(int argc, char **argv) +{ + module_call_init(MODULE_INIT_QOM); + qemu_init_main_loop(&error_abort); + + if (argc !=3D 3) { + fprintf(stderr, "Usage: %s listen_addr connect_addr\n", argv[0]); + exit(-1); + } + + l_addr =3D socket_parse(argv[1], NULL); + c_addr =3D socket_parse(argv[2], NULL); + if (l_addr =3D=3D NULL || c_addr =3D=3D NULL || + l_addr->type !=3D SOCKET_ADDRESS_TYPE_INET || + c_addr->type !=3D SOCKET_ADDRESS_TYPE_INET) { + fprintf(stderr, "Only socket address types 'inet' is supported\n"); + exit(-1); + } + + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/io/channel/rdma/sync", test_io_channel_rdma_sync); + g_test_add_func("/io/channel/rdma/async", test_io_channel_rdma_async); + g_test_add_func("/io/channel/rdma/coroutine", + test_io_channel_rdma_coroutine); + + return g_test_run(); +} --=20 2.43.0