From patchwork Tue Nov 8 04:19:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Wang X-Patchwork-Id: 13035842 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6CDC7C4332F for ; Tue, 8 Nov 2022 04:20:23 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1osG5U-0000Ez-7n; Mon, 07 Nov 2022 23:19:48 -0500 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 1osG5P-0000Dv-FU for qemu-devel@nongnu.org; Mon, 07 Nov 2022 23:19:45 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1osG5N-0004M0-SA for qemu-devel@nongnu.org; Mon, 07 Nov 2022 23:19:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1667881180; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pJ+OeiGs3+ijV+rxOtwuQqouyqdAF7TkTFYOUvVh7eM=; b=jCxF10gVGeC0vG/nIgU9DBDmDiN9vooVijxOJSlwqsyABviOzdYYAd5Fyg21o0Bmfqg2XL ZXMyo91NQ1Pc6nuTlFC1II4hDxmfYHN2RsKEz2L0viUQpTtJbNeNErnV6JKHvIF9g/eQeG weaszO9eXIOXddcc+xlGnkAf6prtDG8= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-131-NWTW4WHuPtir7X0AmyXGsA-1; Mon, 07 Nov 2022 23:19:36 -0500 X-MC-Unique: NWTW4WHuPtir7X0AmyXGsA-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 53D53811E67; Tue, 8 Nov 2022 04:19:36 +0000 (UTC) Received: from localhost.localdomain (ovpn-14-19.pek2.redhat.com [10.72.14.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0BB78112132D; Tue, 8 Nov 2022 04:19:33 +0000 (UTC) From: Jason Wang To: stefanha@redhat.com Cc: qemu-devel@nongnu.org, Si-Wei Liu , Eugenio Perez Martin , Jason Wang Subject: [PULL 1/2] vhost-vdpa: fix assert !virtio_net_get_subqueue(nc)->async_tx.elem in virtio_net_reset Date: Tue, 8 Nov 2022 12:19:28 +0800 Message-Id: <20221108041929.18417-2-jasowang@redhat.com> In-Reply-To: <20221108041929.18417-1-jasowang@redhat.com> References: <20221108041929.18417-1-jasowang@redhat.com> MIME-Version: 1.0 Content-type: text/plain X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 Received-SPF: pass client-ip=170.10.129.124; envelope-from=jasowang@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 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: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Si-Wei Liu The citing commit has incorrect code in vhost_vdpa_receive() that returns zero instead of full packet size to the caller. This renders pending packets unable to be freed so then get clogged in the tx queue forever. When device is being reset later on, below assertion failure ensues: 0 0x00007f86d53bb387 in raise () from /lib64/libc.so.6 1 0x00007f86d53bca78 in abort () from /lib64/libc.so.6 2 0x00007f86d53b41a6 in __assert_fail_base () from /lib64/libc.so.6 3 0x00007f86d53b4252 in __assert_fail () from /lib64/libc.so.6 4 0x000055b8f6ff6fcc in virtio_net_reset (vdev=) at /usr/src/debug/qemu/hw/net/virtio-net.c:563 5 0x000055b8f7012fcf in virtio_reset (opaque=0x55b8faf881f0) at /usr/src/debug/qemu/hw/virtio/virtio.c:1993 6 0x000055b8f71f0086 in virtio_bus_reset (bus=bus@entry=0x55b8faf88178) at /usr/src/debug/qemu/hw/virtio/virtio-bus.c:102 7 0x000055b8f71f1620 in virtio_pci_reset (qdev=) at /usr/src/debug/qemu/hw/virtio/virtio-pci.c:1845 8 0x000055b8f6fafc6c in memory_region_write_accessor (mr=, addr=, value=, size=, shift=, mask=, attrs=...) at /usr/src/debug/qemu/memory.c:483 9 0x000055b8f6fadce9 in access_with_adjusted_size (addr=addr@entry=20, value=value@entry=0x7f867e7fb7e8, size=size@entry=1, access_size_min=, access_size_max=, access_fn=0x55b8f6fafc20 , mr=0x55b8faf80a50, attrs=...) at /usr/src/debug/qemu/memory.c:544 10 0x000055b8f6fb1d0b in memory_region_dispatch_write (mr=mr@entry=0x55b8faf80a50, addr=addr@entry=20, data=0, op=, attrs=attrs@entry=...) at /usr/src/debug/qemu/memory.c:1470 11 0x000055b8f6f62ada in flatview_write_continue (fv=fv@entry=0x7f86ac04cd20, addr=addr@entry=549755813908, attrs=..., attrs@entry=..., buf=buf@entry=0x7f86d0223028
, len=len@entry=1, addr1=20, l=1, mr=0x55b8faf80a50) at /usr/src/debug/qemu/exec.c:3266 12 0x000055b8f6f62c8f in flatview_write (fv=0x7f86ac04cd20, addr=549755813908, attrs=..., buf=0x7f86d0223028
, len=1) at /usr/src/debug/qemu/exec.c:3306 13 0x000055b8f6f674cb in address_space_write (as=, addr=, attrs=..., buf=, len=) at /usr/src/debug/qemu/exec.c:3396 14 0x000055b8f6f67575 in address_space_rw (as=, addr=, attrs=..., attrs@entry=..., buf=buf@entry=0x7f86d0223028
, len=, is_write=) at /usr/src/debug/qemu/exec.c:3406 15 0x000055b8f6fc1cc8 in kvm_cpu_exec (cpu=cpu@entry=0x55b8f9aa0e10) at /usr/src/debug/qemu/accel/kvm/kvm-all.c:2410 16 0x000055b8f6fa5f5e in qemu_kvm_cpu_thread_fn (arg=0x55b8f9aa0e10) at /usr/src/debug/qemu/cpus.c:1318 17 0x000055b8f7336e16 in qemu_thread_start (args=0x55b8f9ac8480) at /usr/src/debug/qemu/util/qemu-thread-posix.c:519 18 0x00007f86d575aea5 in start_thread () from /lib64/libpthread.so.0 19 0x00007f86d5483b2d in clone () from /lib64/libc.so.6 Make vhost_vdpa_receive() return the size passed in as is, so that the caller qemu_deliver_packet_iov() would eventually propagate it back to virtio_net_flush_tx() to release pending packets from the async_tx queue. Which corresponds to the drop path where qemu_sendv_packet_async() returns non-zero in virtio_net_flush_tx(). Fixes: 846a1e85da64 ("vdpa: Add dummy receive callback") Cc: Eugenio Perez Martin Signed-off-by: Si-Wei Liu Signed-off-by: Jason Wang --- net/vhost-vdpa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index e370ecb..6811089 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -210,7 +210,7 @@ static bool vhost_vdpa_check_peer_type(NetClientState *nc, ObjectClass *oc, static ssize_t vhost_vdpa_receive(NetClientState *nc, const uint8_t *buf, size_t size) { - return 0; + return size; } static NetClientInfo net_vhost_vdpa_info = { From patchwork Tue Nov 8 04:19:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Wang X-Patchwork-Id: 13035843 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EE25BC433FE for ; Tue, 8 Nov 2022 04:20:37 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1osG5T-0000Ex-Nx; Mon, 07 Nov 2022 23:19:47 -0500 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 1osG5Q-0000Dy-Vk for qemu-devel@nongnu.org; Mon, 07 Nov 2022 23:19:45 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1osG5O-0004M4-RY for qemu-devel@nongnu.org; Mon, 07 Nov 2022 23:19:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1667881182; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=U4rwTbx0Jx9+U35B/T3F/MuX1VBcp4D+gBRZpEwH85I=; b=J2NUTrLkI0oG+p/bhZlfzrYsX2B9x53WqtUIbDK6jn17FxWfqlJvfct0WQQBabKHqkFSDU efjKLxutz+T622b4sz7f7Cl0GpCKO87SG2rCfo/Ql+nm/S/BNzrTYf0Axh4ehE4KbLeEfj TvqJfKdyuMTnLy34Sp/gUTy94gX4Z90= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-498-2g4WXc6nMc-qy_n1ta6C8Q-1; Mon, 07 Nov 2022 23:19:39 -0500 X-MC-Unique: 2g4WXc6nMc-qy_n1ta6C8Q-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6DD2C833A06 for ; Tue, 8 Nov 2022 04:19:39 +0000 (UTC) Received: from localhost.localdomain (ovpn-14-19.pek2.redhat.com [10.72.14.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 17E40112132D; Tue, 8 Nov 2022 04:19:36 +0000 (UTC) From: Jason Wang To: stefanha@redhat.com Cc: qemu-devel@nongnu.org, Laurent Vivier , "Michael S . Tsirkin" , Jason Wang Subject: [PULL 2/2] tests/qtest: netdev: test stream and dgram backends Date: Tue, 8 Nov 2022 12:19:29 +0800 Message-Id: <20221108041929.18417-3-jasowang@redhat.com> In-Reply-To: <20221108041929.18417-1-jasowang@redhat.com> References: <20221108041929.18417-1-jasowang@redhat.com> MIME-Version: 1.0 Content-type: text/plain X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 Received-SPF: pass client-ip=170.10.133.124; envelope-from=jasowang@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 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: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Laurent Vivier Signed-off-by: Laurent Vivier Acked-by: Michael S. Tsirkin Signed-off-by: Jason Wang --- tests/qtest/meson.build | 2 + tests/qtest/netdev-socket.c | 435 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 437 insertions(+) create mode 100644 tests/qtest/netdev-socket.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index c07a5b1..43d075b 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -27,6 +27,7 @@ qtests_generic = [ 'test-hmp', 'qos-test', 'readconfig-test', + 'netdev-socket', ] if config_host.has_key('CONFIG_MODULES') qtests_generic += [ 'modules-test' ] @@ -304,6 +305,7 @@ qtests = { 'tpm-tis-device-swtpm-test': [io, tpmemu_files, 'tpm-tis-util.c'], 'tpm-tis-device-test': [io, tpmemu_files, 'tpm-tis-util.c'], 'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'), + 'netdev-socket': files('netdev-socket.c', '../unit/socket-helpers.c'), } gvnc = dependency('gvnc-1.0', required: false) diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c new file mode 100644 index 0000000..dd46214 --- /dev/null +++ b/tests/qtest/netdev-socket.c @@ -0,0 +1,435 @@ +/* + * QTest testcase for netdev stream and dgram + * + * Copyright (c) 2022 Red Hat, Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include +#include "../unit/socket-helpers.h" +#include "libqtest.h" + +#define CONNECTION_TIMEOUT 5 + +#define EXPECT_STATE(q, e, t) \ +do { \ + char *resp = qtest_hmp(q, "info network"); \ + if (t) { \ + strrchr(resp, t)[0] = 0; \ + } \ + g_test_timer_start(); \ + while (g_test_timer_elapsed() < CONNECTION_TIMEOUT) { \ + if (strcmp(resp, e) == 0) { \ + break; \ + } \ + g_free(resp); \ + resp = qtest_hmp(q, "info network"); \ + if (t) { \ + strrchr(resp, t)[0] = 0; \ + } \ + } \ + g_assert_cmpstr(resp, ==, e); \ + g_free(resp); \ +} while (0) + +static char *tmpdir; + +static int inet_get_free_port_socket_ipv4(int sock) +{ + struct sockaddr_in addr; + socklen_t len; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = 0; + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + return -1; + } + + len = sizeof(addr); + if (getsockname(sock, (struct sockaddr *)&addr, &len) < 0) { + return -1; + } + + return ntohs(addr.sin_port); +} + +static int inet_get_free_port_socket_ipv6(int sock) +{ + struct sockaddr_in6 addr; + socklen_t len; + + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr = in6addr_any; + addr.sin6_port = 0; + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + return -1; + } + + len = sizeof(addr); + if (getsockname(sock, (struct sockaddr *)&addr, &len) < 0) { + return -1; + } + + return ntohs(addr.sin6_port); +} + +static int inet_get_free_port_multiple(int nb, int *port, bool ipv6) +{ + int sock[nb]; + int i; + + for (i = 0; i < nb; i++) { + sock[i] = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0); + if (sock[i] < 0) { + break; + } + port[i] = ipv6 ? inet_get_free_port_socket_ipv6(sock[i]) : + inet_get_free_port_socket_ipv4(sock[i]); + if (port[i] == -1) { + break; + } + } + + nb = i; + for (i = 0; i < nb; i++) { + closesocket(sock[i]); + } + + return nb; +} + +static int inet_get_free_port(bool ipv6) +{ + int nb, port; + + nb = inet_get_free_port_multiple(1, &port, ipv6); + g_assert_cmpint(nb, ==, 1); + + return port; +} + +static void test_stream_inet_ipv4(void) +{ + QTestState *qts0, *qts1; + char *expect; + int port; + + port = inet_get_free_port(false); + qts0 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,server=true,addr.type=inet," + "addr.ipv4=on,addr.ipv6=off," + "addr.host=127.0.0.1,addr.port=%d", port); + + EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0); + + qts1 = qtest_initf("-nodefaults " + "-netdev stream,server=false,id=st0,addr.type=inet," + "addr.ipv4=on,addr.ipv6=off," + "addr.host=127.0.0.1,addr.port=%d", port); + + expect = g_strdup_printf("st0: index=0,type=stream,tcp:127.0.0.1:%d\r\n", + port); + EXPECT_STATE(qts1, expect, 0); + g_free(expect); + + /* the port is unknown, check only the address */ + EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:127.0.0.1", ':'); + + qtest_quit(qts1); + qtest_quit(qts0); +} + +static void test_stream_inet_ipv6(void) +{ + QTestState *qts0, *qts1; + char *expect; + int port; + + port = inet_get_free_port(true); + qts0 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,server=true,addr.type=inet," + "addr.ipv4=off,addr.ipv6=on," + "addr.host=::1,addr.port=%d", port); + + EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0); + + qts1 = qtest_initf("-nodefaults " + "-netdev stream,server=false,id=st0,addr.type=inet," + "addr.ipv4=off,addr.ipv6=on," + "addr.host=::1,addr.port=%d", port); + + expect = g_strdup_printf("st0: index=0,type=stream,tcp:::1:%d\r\n", + port); + EXPECT_STATE(qts1, expect, 0); + g_free(expect); + + /* the port is unknown, check only the address */ + EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:::1", ':'); + + qtest_quit(qts1); + qtest_quit(qts0); +} + +static void test_stream_unix(void) +{ + QTestState *qts0, *qts1; + char *expect; + gchar *path; + + path = g_strconcat(tmpdir, "/stream_unix", NULL); + + qts0 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,server=true," + "addr.type=unix,addr.path=%s,", + path); + + EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0); + + qts1 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,server=false," + "addr.type=unix,addr.path=%s", + path); + + expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path); + EXPECT_STATE(qts1, expect, 0); + EXPECT_STATE(qts0, expect, 0); + g_free(expect); + g_free(path); + + qtest_quit(qts1); + qtest_quit(qts0); +} + +static void test_stream_unix_abstract(void) +{ + QTestState *qts0, *qts1; + char *expect; + gchar *path; + + path = g_strconcat(tmpdir, "/stream_unix_abstract", NULL); + + qts0 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,server=true," + "addr.type=unix,addr.path=%s," + "addr.abstract=on", + path); + + EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0); + + qts1 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,server=false," + "addr.type=unix,addr.path=%s,addr.abstract=on", + path); + + expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path); + EXPECT_STATE(qts1, expect, 0); + EXPECT_STATE(qts0, expect, 0); + g_free(expect); + g_free(path); + + qtest_quit(qts1); + qtest_quit(qts0); +} + +static void test_stream_fd(void) +{ + QTestState *qts0, *qts1; + int sock[2]; + int ret; + + ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, sock); + g_assert_true(ret == 0); + + qts0 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,addr.type=fd,addr.str=%d", + sock[0]); + + EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0); + + qts1 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,addr.type=fd,addr.str=%d", + sock[1]); + + EXPECT_STATE(qts1, "st0: index=0,type=stream,unix:\r\n", 0); + EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0); + + qtest_quit(qts1); + qtest_quit(qts0); + + closesocket(sock[0]); + closesocket(sock[1]); +} + +static void test_dgram_inet(void) +{ + QTestState *qts0, *qts1; + char *expect; + int port[2]; + int nb; + + nb = inet_get_free_port_multiple(2, port, false); + g_assert_cmpint(nb, ==, 2); + + qts0 = qtest_initf("-nodefaults " + "-netdev dgram,id=st0," + "local.type=inet,local.host=127.0.0.1,local.port=%d," + "remote.type=inet,remote.host=127.0.0.1,remote.port=%d", + port[0], port[1]); + + expect = g_strdup_printf("st0: index=0,type=dgram," + "udp=127.0.0.1:%d/127.0.0.1:%d\r\n", + port[0], port[1]); + EXPECT_STATE(qts0, expect, 0); + g_free(expect); + + qts1 = qtest_initf("-nodefaults " + "-netdev dgram,id=st0," + "local.type=inet,local.host=127.0.0.1,local.port=%d," + "remote.type=inet,remote.host=127.0.0.1,remote.port=%d", + port[1], port[0]); + + expect = g_strdup_printf("st0: index=0,type=dgram," + "udp=127.0.0.1:%d/127.0.0.1:%d\r\n", + port[1], port[0]); + EXPECT_STATE(qts1, expect, 0); + g_free(expect); + + qtest_quit(qts1); + qtest_quit(qts0); +} + +static void test_dgram_mcast(void) +{ + QTestState *qts; + + qts = qtest_initf("-nodefaults " + "-netdev dgram,id=st0," + "remote.type=inet,remote.host=230.0.0.1,remote.port=1234"); + + EXPECT_STATE(qts, "st0: index=0,type=dgram,mcast=230.0.0.1:1234\r\n", 0); + + qtest_quit(qts); +} + +static void test_dgram_unix(void) +{ + QTestState *qts0, *qts1; + char *expect; + gchar *path0, *path1; + + path0 = g_strconcat(tmpdir, "/dgram_unix0", NULL); + path1 = g_strconcat(tmpdir, "/dgram_unix1", NULL); + + qts0 = qtest_initf("-nodefaults " + "-netdev dgram,id=st0,local.type=unix,local.path=%s," + "remote.type=unix,remote.path=%s", + path0, path1); + + expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n", + path0, path1); + EXPECT_STATE(qts0, expect, 0); + g_free(expect); + + qts1 = qtest_initf("-nodefaults " + "-netdev dgram,id=st0,local.type=unix,local.path=%s," + "remote.type=unix,remote.path=%s", + path1, path0); + + + expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n", + path1, path0); + EXPECT_STATE(qts1, expect, 0); + g_free(expect); + + unlink(path0); + g_free(path0); + unlink(path1); + g_free(path1); + + qtest_quit(qts1); + qtest_quit(qts0); +} + +static void test_dgram_fd(void) +{ + QTestState *qts0, *qts1; + char *expect; + int ret; + int sv[2]; + + ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, sv); + g_assert_cmpint(ret, !=, -1); + + qts0 = qtest_initf("-nodefaults " + "-netdev dgram,id=st0,local.type=fd,local.str=%d", + sv[0]); + + expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[0]); + EXPECT_STATE(qts0, expect, 0); + g_free(expect); + + qts1 = qtest_initf("-nodefaults " + "-netdev dgram,id=st0,local.type=fd,local.str=%d", + sv[1]); + + + expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[1]); + EXPECT_STATE(qts1, expect, 0); + g_free(expect); + + qtest_quit(qts1); + qtest_quit(qts0); + + closesocket(sv[0]); + closesocket(sv[1]); +} + +int main(int argc, char **argv) +{ + int ret; + bool has_ipv4, has_ipv6, has_afunix; + gchar dir[] = "/tmp/netdev-socket.XXXXXX"; + + g_test_init(&argc, &argv, NULL); + + if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) { + g_printerr("socket_check_protocol_support() failed\n"); + goto end; + } + + if (g_mkdtemp(dir) == NULL) { + g_error("g_mkdtemp: %s", g_strerror(errno)); + } + tmpdir = dir; + + if (has_ipv4) { + qtest_add_func("/netdev/stream/inet/ipv4", test_stream_inet_ipv4); + qtest_add_func("/netdev/dgram/inet", test_dgram_inet); + qtest_add_func("/netdev/dgram/mcast", test_dgram_mcast); + } + if (has_ipv6) { + qtest_add_func("/netdev/stream/inet/ipv6", test_stream_inet_ipv6); + } + + socket_check_afunix_support(&has_afunix); + if (has_afunix) { + qtest_add_func("/netdev/dgram/unix", test_dgram_unix); + qtest_add_func("/netdev/stream/unix", test_stream_unix); + qtest_add_func("/netdev/stream/unix/abstract", + test_stream_unix_abstract); + qtest_add_func("/netdev/stream/fd", test_stream_fd); + qtest_add_func("/netdev/dgram/fd", test_dgram_fd); + } + +end: + ret = g_test_run(); + + g_rmdir(dir); + + return ret; +}