From patchwork Tue Oct 11 20:05:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004316 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 0842CC433FE for ; Tue, 11 Oct 2022 20:24:49 +0000 (UTC) Received: from localhost ([::1]:36900 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLnz-00044u-US for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:24:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55712) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVt-0006P3-Eg for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:07 -0400 Received: from mout.kundenserver.de ([212.227.126.135]:60945) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVr-0003jx-Dl for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:05 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MTi9N-1oaKFb04YX-00U0LJ; Tue, 11 Oct 2022 22:05:46 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org, Stefano Brivio Subject: [PATCH v11 01/17] net: introduce convert_host_port() Date: Tue, 11 Oct 2022 22:05:23 +0200 Message-Id: <20221011200539.1486809-2-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:2rCa7hLvyE2m+t/FaH4OXrdNULbkjAfH/Ah10xH5vvl+unpLrqE iJz/zdsuYim5ODAiHNt8oZk5AWyiFAMp25IrzAl9owmBMxhOqcGnBf/5S/lhDm0JxYqkSBF u5fD92MXtc9tWCXkNKMxvyKHEcG00uFe9DFNVrxEvaySMRN6bjOIyxzE3m7hIx9M2/lEQhZ VDelg4186j/qJJegiJ2Uw== X-UI-Out-Filterresults: notjunk:1;V03:K0:uM0fSt3TyeI=:l62C1NPiRHzV4ufs46Iv6B gEkdbu9QwdXpeDLTOr2oi0SXgDBcCCYWzhYFumSAsyHYO4U7wJ8YTykA0Hu9v34ST/5mnzDLP n5MVoKEY7MQ3LylWHVyU+zH4U29uthuS61luX6bnNCNO7F2f7g+XdLmlhbX2TUpzOvMjDHADq 6rjLrL8KHsIEBR04chw90svrnPY26QZvpMlZYsFgFKaTkF9WDL0UgM8Oyt2AwoJHa5BZxoQp1 zjSKmiz3SqJbdf4UETIL2le8dH2Bb0zsAYZnfRB42hphsra32wc+l0WG7KQ90XOkz8hBQC5cS 5SsLDADD8OBh0vN1sEmHhSMVeVuCbUJhvfhcsN2tPIcmN2ejbxMtmCzT75lGcMX8A354A4LoV dhTDVaq9w9SvemmWSYnl3ETgj0nW6tAmkPcKoMcy1lc52H6FeKZybGCT2INViqSFhnoIs1iTf SJFt1JWj/KRrPQ+NXpdENq1m71lcInfVuNJyBWQ0jlMflqp5xlaZCQIt7jHcZcxUZq8Gy+HV0 NlrE/xL7wu2e+ukC0fF/ir788VljFSeUhbGkvLbfHlJJASsBQK0oO3746dDIV5LSChBV7W9oG 5rblpRyJpWg/0oHDQ5Zhxk4tPRRRlud3krPldEahD04sv5MFc6P/sDA+OsXRetVSP8HUO7DfF cUfOaRRXxwFBmIBKktas39YtVECFPoi0m7ITU+SDPh0hNKb6ru3OoPR5vBf/jznNCE4Ax5XGd r44JzaS2li+3VluASmyoD0psLDH5F14CB6LwTA823gNhIi8FQ3U9cQjo44yWN5V/DRBTwzjfL q7rEg6U Received-SPF: permerror client-ip=212.227.126.135; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" Signed-off-by: Laurent Vivier Reviewed-by: Stefano Brivio Reviewed-by: David Gibson Acked-by: Michael S. Tsirkin --- include/qemu/sockets.h | 2 ++ net/net.c | 62 ++++++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index 036745e58653..db4bedb6fa20 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -65,6 +65,8 @@ void socket_listen_cleanup(int fd, Error **errp); int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp); /* Old, ipv4 only bits. Don't use for new code. */ +int convert_host_port(struct sockaddr_in *saddr, const char *host, + const char *port, Error **errp); int parse_host_port(struct sockaddr_in *saddr, const char *str, Error **errp); int socket_init(void); diff --git a/net/net.c b/net/net.c index 2db160e0634d..d2288bd3a929 100644 --- a/net/net.c +++ b/net/net.c @@ -66,55 +66,57 @@ static QTAILQ_HEAD(, NetClientState) net_clients; /***********************************************************/ /* network device redirectors */ -int parse_host_port(struct sockaddr_in *saddr, const char *str, - Error **errp) +int convert_host_port(struct sockaddr_in *saddr, const char *host, + const char *port, Error **errp) { - gchar **substrings; struct hostent *he; - const char *addr, *p, *r; - int port, ret = 0; + const char *r; + long p; memset(saddr, 0, sizeof(*saddr)); - substrings = g_strsplit(str, ":", 2); - if (!substrings || !substrings[0] || !substrings[1]) { - error_setg(errp, "host address '%s' doesn't contain ':' " - "separating host from port", str); - ret = -1; - goto out; - } - - addr = substrings[0]; - p = substrings[1]; - saddr->sin_family = AF_INET; - if (addr[0] == '\0') { + if (host[0] == '\0') { saddr->sin_addr.s_addr = 0; } else { - if (qemu_isdigit(addr[0])) { - if (!inet_aton(addr, &saddr->sin_addr)) { + if (qemu_isdigit(host[0])) { + if (!inet_aton(host, &saddr->sin_addr)) { error_setg(errp, "host address '%s' is not a valid " - "IPv4 address", addr); - ret = -1; - goto out; + "IPv4 address", host); + return -1; } } else { - he = gethostbyname(addr); + he = gethostbyname(host); if (he == NULL) { - error_setg(errp, "can't resolve host address '%s'", addr); - ret = -1; - goto out; + error_setg(errp, "can't resolve host address '%s'", host); + return -1; } saddr->sin_addr = *(struct in_addr *)he->h_addr; } } - port = strtol(p, (char **)&r, 0); - if (r == p) { - error_setg(errp, "port number '%s' is invalid", p); + if (qemu_strtol(port, &r, 0, &p) != 0) { + error_setg(errp, "port number '%s' is invalid", port); + return -1; + } + saddr->sin_port = htons(p); + return 0; +} + +int parse_host_port(struct sockaddr_in *saddr, const char *str, + Error **errp) +{ + gchar **substrings; + int ret; + + substrings = g_strsplit(str, ":", 2); + if (!substrings || !substrings[0] || !substrings[1]) { + error_setg(errp, "host address '%s' doesn't contain ':' " + "separating host from port", str); ret = -1; goto out; } - saddr->sin_port = htons(port); + + ret = convert_host_port(saddr, substrings[0], substrings[1], errp); out: g_strfreev(substrings); From patchwork Tue Oct 11 20:05:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004306 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 610DCC433FE for ; Tue, 11 Oct 2022 20:09:38 +0000 (UTC) Received: from localhost ([::1]:40040 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLZI-0000s0-Ru for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:09:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55710) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVs-0006P2-MJ for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:07 -0400 Received: from mout.kundenserver.de ([212.227.126.130]:39477) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVq-0003k2-RA for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:04 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MAwoL-1ot65S1nlB-00BN1x; Tue, 11 Oct 2022 22:05:47 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org Subject: [PATCH v11 02/17] net: remove the @errp argument of net_client_inits() Date: Tue, 11 Oct 2022 22:05:24 +0200 Message-Id: <20221011200539.1486809-3-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:oGEBk+kOtZqR+pDtNXAb1wihBVS+zvLLwV9nHiBb/Vn9T82eAsh LINI2qKGCfVw+EfpiB7OZsISLobzstbA+38KHNTbHbJgfC6MvWXPmhZ7219Qg0COGXO86TQ hE+MqoQLFDPn3/+LcUAq2qvMZ5/ttWbdkGjmOU8wg9H0ZPstU1XLoosnE6elRaLIsO094Wj C+lvOUPNJLM5S7TJdO69A== X-UI-Out-Filterresults: notjunk:1;V03:K0:5DVblCvFshk=:7yIAdecSFiVuIgVKYNPA1a WRgwAPtFkLmTM4oGZtX/JM/AaIndu/QH5NpQnWsT5g2c44qY3klDkgNhRK+v6V5kJRFMQAQnx enuT98/PX2VGMNZ3bsdmDzOEKBxWdReqHo6iQD7ii7j2bwD2ipw+kzDBxO+o/DFLtkt/6SLz1 R5JH9i9cdghjPCe7eNm/GO24z4NoeahEuugcqyb8IWWm3ZQOrHdIDph0cTFRjG9yqs9aer4/h mYKzS6ObaMLeR7HqYk4slXxqrg5qDR3A3bT5i4S3aKf1a5QwaRFA6w2oUQYCWgzribiOz/lK3 faJ/kYu/aZ4E+20k9aCdaBHYVLnWZ3UhHoHo68cVsB7AEixxHnKwFAfRV/P0YXYOdzbWC+Inh lmGXqa6QtOUchQH1NXqqbG2N92ygu7ToYzPypKR3N5YdLmratEith5SEgx/NqaJY8S+dLrfKt pAAU+yV8utccsFyl7k/mIGbTe+nZwMSbmDW+DYRvbMa5iXTyCJSSd/QmBoPup+9qqvtuPqUq6 adi2oF5V04ClxguiyKRlUzaEyWEr9to/Bs32Ayb6NQsYidT8VgwMfqhZYCS/YP5gPbOlnOZUW scYQP57lXVHEHpuogBtn4Ywxm0tuK1I7P9e6pEZh2/5r9mtD/2XH8im6k7qCgVjkAnoB3K9NB BOJdLRU3A8yjHfZrJsDvTHRxVndX6ulEk5dniCqgg4I+ahsrHcCcuFhbXEARzXVI71n3hXM9p /vzLZjO/ynFWaNVwjNR5U4wqlc21pzcxWJKh1qHdrnkZCVhE6SJO4vs7IqeUx218I01/JuOOU olo6Huz Received-SPF: permerror client-ip=212.227.126.130; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" The only caller passes &error_fatal, so use this directly in the function. It's what we do for -blockdev, -device, and -object. Suggested-by: Markus Armbruster Signed-off-by: Laurent Vivier Reviewed-by: Markus Armbruster Reviewed-by: David Gibson Acked-by: Michael S. Tsirkin --- include/net/net.h | 2 +- net/net.c | 20 +++++++------------- softmmu/vl.c | 2 +- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/include/net/net.h b/include/net/net.h index 81d0b21defce..c1c34a58f849 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -222,7 +222,7 @@ extern const char *host_net_devices[]; /* from net.c */ int net_client_parse(QemuOptsList *opts_list, const char *str); void show_netdevs(void); -int net_init_clients(Error **errp); +void net_init_clients(void); void net_check_clients(void); void net_cleanup(void); void hmp_host_net_add(Monitor *mon, const QDict *qdict); diff --git a/net/net.c b/net/net.c index d2288bd3a929..15958f881776 100644 --- a/net/net.c +++ b/net/net.c @@ -1562,27 +1562,21 @@ out: return ret; } -int net_init_clients(Error **errp) +void net_init_clients(void) { net_change_state_entry = qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL); QTAILQ_INIT(&net_clients); - if (qemu_opts_foreach(qemu_find_opts("netdev"), - net_init_netdev, NULL, errp)) { - return -1; - } - - if (qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL, errp)) { - return -1; - } + qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, + &error_fatal); - if (qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL, errp)) { - return -1; - } + qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL, + &error_fatal); - return 0; + qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL, + &error_fatal); } int net_client_parse(QemuOptsList *opts_list, const char *optarg) diff --git a/softmmu/vl.c b/softmmu/vl.c index b464da25bcde..a4ae131e4d61 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1904,7 +1904,7 @@ static void qemu_create_late_backends(void) qtest_server_init(qtest_chrdev, qtest_log, &error_fatal); } - net_init_clients(&error_fatal); + net_init_clients(); object_option_foreach_add(object_create_late); From patchwork Tue Oct 11 20:05:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004314 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 61C2CC433F5 for ; Tue, 11 Oct 2022 20:16:02 +0000 (UTC) Received: from localhost ([::1]:58680 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLfV-00076J-5F for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:16:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55706) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVs-0006P0-1S for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:05 -0400 Received: from mout.kundenserver.de ([212.227.126.133]:52813) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVp-0003ja-8U for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:03 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1M1YtP-1okocB3Lid-0039YN; Tue, 11 Oct 2022 22:05:49 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org Subject: [PATCH v11 03/17] net: simplify net_client_parse() error management Date: Tue, 11 Oct 2022 22:05:25 +0200 Message-Id: <20221011200539.1486809-4-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:A9ouqfM3UJq93QDzTpjBZLmdCU8DHJePfXwKGc5MkczBHI3sW8v 8hg1116Rahdg3557QLZwWeMx2dlypFtcnm6WSWZqA1+64PK3n1gcB7RspijG0Yd38/ejcRU 6+zV5dp+TvSzYC+DcjNcbGW7mfyHPiIhKhuijsG5g5SFyDH2C+rBL0qYJSqs7DHUVgmwGnB 1D8u3TEscMxLfJXrxK6WA== X-UI-Out-Filterresults: notjunk:1;V03:K0:ln7jyWV2rEg=:P8ap6lfjsJUu5IQwLMkGnM fX7aX/43ttx5lC6LF5fVsDhsCqxOfMUT3AiMYuL+GGIzZiwIlc5GaWpx4+ESYUIn/RQW4F235 KtCawN2/RYu1EEZgnmi6vnmzq3aqSNr5JcswxUAR3sgaN73BtFzkn2o7OUNMeCWsCqlJWs7cT RQNBNv5cYxnTINJoHPCAjjbjq5zvVMQU6yPG0KtMVgJcZZyWUsr3/ECvA7DxmxTSD9jAMTT8b dnzn8PuA7siPXVL7IWGTKqoqmSeqsyRmMUSwI+n4dFoXyh2l1U76cjNUmBusiZHSQWYC+ytsv RxpEki7wHOdIxVcupm9AjjTqjVx7XlTF+D98T4FZn0RCRf4e94ZaXhO4mO/fKk3ZWQMZVZIX6 ATUc7FtpwCD4h9oy3wb7ZB4Agu0AH4/Q8is8eYEaxfde7mP9W5JAnHqIkP74SY5CNpGBeelUR arq5AeZK2HQKqTqWwmlISc5U2Gc6bmUSchTJ9CBCfw9pksZ5EbmwFxlFl4GFofL0zL19VO/Ei UVxjn6o1eAT8AviW+4IR0E+O+JTxmb1Z9vN0keMooA5rBCvhURH//tBJe3H5G4oLgnmSrmFnD DDt6yjOjPtZ25tzlOLfH4LZTQatrx4lRTOekr93kNye4M8Y53/WZDLHuz0c5TmDjEHBZSsGCT rReOOSXjzI/bGnE+kUy4PBaO8Qq19a/Azj6QOv7vsCty9Pf9HVQUbu/wXRQXMp1uHcFgVf+1+ twgPB/11Q/s9jwnVvRMC/ixzqPCPX3DnZej/iJwjfysRzcf3/epvKyG11lxEXGrA1ATUGggBW x0zLqsa Received-SPF: permerror client-ip=212.227.126.133; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" All net_client_parse() callers exit in case of error. Move exit(1) to net_client_parse() and remove error checking from the callers. Suggested-by: Markus Armbruster Signed-off-by: Laurent Vivier Reviewed-by: Markus Armbruster Reviewed-by: David Gibson Acked-by: Michael S. Tsirkin --- include/net/net.h | 2 +- net/net.c | 6 ++---- softmmu/vl.c | 12 +++--------- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/include/net/net.h b/include/net/net.h index c1c34a58f849..55023e7e9fa9 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -220,7 +220,7 @@ extern NICInfo nd_table[MAX_NICS]; extern const char *host_net_devices[]; /* from net.c */ -int net_client_parse(QemuOptsList *opts_list, const char *str); +void net_client_parse(QemuOptsList *opts_list, const char *str); void show_netdevs(void); void net_init_clients(void); void net_check_clients(void); diff --git a/net/net.c b/net/net.c index 15958f881776..f056e8aebfb2 100644 --- a/net/net.c +++ b/net/net.c @@ -1579,13 +1579,11 @@ void net_init_clients(void) &error_fatal); } -int net_client_parse(QemuOptsList *opts_list, const char *optarg) +void net_client_parse(QemuOptsList *opts_list, const char *optarg) { if (!qemu_opts_parse_noisily(opts_list, optarg, true)) { - return -1; + exit(1); } - - return 0; } /* From FreeBSD */ diff --git a/softmmu/vl.c b/softmmu/vl.c index a4ae131e4d61..e69aa43de469 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2801,21 +2801,15 @@ void qemu_init(int argc, char **argv) break; case QEMU_OPTION_netdev: default_net = 0; - if (net_client_parse(qemu_find_opts("netdev"), optarg) == -1) { - exit(1); - } + net_client_parse(qemu_find_opts("netdev"), optarg); break; case QEMU_OPTION_nic: default_net = 0; - if (net_client_parse(qemu_find_opts("nic"), optarg) == -1) { - exit(1); - } + net_client_parse(qemu_find_opts("nic"), optarg); break; case QEMU_OPTION_net: default_net = 0; - if (net_client_parse(qemu_find_opts("net"), optarg) == -1) { - exit(1); - } + net_client_parse(qemu_find_opts("net"), optarg); break; #ifdef CONFIG_LIBISCSI case QEMU_OPTION_iscsi: From patchwork Tue Oct 11 20:05:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004307 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 D3723C4332F for ; Tue, 11 Oct 2022 20:09:39 +0000 (UTC) Received: from localhost ([::1]:40026 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLZK-0000qa-Mt for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:09:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55708) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVs-0006P1-LI for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:07 -0400 Received: from mout.kundenserver.de ([212.227.126.135]:50521) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVp-0003jf-9O for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:04 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MQ6C0-1oV5yg0wMK-00M2FA; Tue, 11 Oct 2022 22:05:50 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org Subject: [PATCH v11 04/17] qapi: net: introduce a way to bypass qemu_opts_parse_noisily() Date: Tue, 11 Oct 2022 22:05:26 +0200 Message-Id: <20221011200539.1486809-5-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:czMHkDkkqeIXGC5qBtBBJS9E3R+8iAb+tiHYhdF9yBURR1ndHa6 HyseRsw6hXxr8C0e8ApsILNkrsyA7JRoMl7JzyocaYXlS2SkzChNjn+5Bqe19Wa0viD4/t+ LrFmMTXEeH2FxcG8Ux5Gveuno4OUDhjHrAgJAx2kqDxPGGZHGVz6CdYChKQ+MpJ0lLPkhqR 6S4RH7ti/+hUqmUhsGO/A== X-UI-Out-Filterresults: notjunk:1;V03:K0:7zEF/nwbU8Q=:EmR44orMNwzKhBn4AVGwfi 1kiyd5nyuX+WrE1w5bfgpfKPQovbt0XTs+/FFKHF2eXorcPVAoJDmclUowOXkc2MwxFkcBqss 3DycEUnzdsk5NkANY2YrwsCMa0isMOwwZFDhPOl1HXO+e+5c8hDfSuGDWlsQM+bQ5+8UYQj46 pAs8x3YFZFi76TPpleExJ97jr1aOiKK9eOb+OClYjeoiMRaNUQefyV3QHRqe8LEkIj6gVAkMQ XmytMcknNthjnGjth6HfEq0UiKk7i69FkdJKzFvriimHfwzr0TfsZWeg0zpnJ72I0iqJ4lhtz +akxaUXA2XAb15xtSp7kZAo2VdlpvBONmWquwTQ+hXXG7EhGr0Vr6kPDPbcy0lfBG8vKldu8V dOhh2hunhwNCznhuJ91Z4xvGpk62cyufc6qNn7Bn/UmPlHssSz40uhjLE4c5DnOADON3RMcKu VKyvFbgBpspNdiGnblUTJbFA7yZyzHUchI4TNR7buDl9Kmet2y9GzU1pSWPOfvO5rQgYrnR1r 6ZayX6qOTl1+ZuyZwMIjwz3qrFFqsEcMGtEYsS7QizDwykc3Hh49uAn0tMj1j/OPrMwted4sk M8S8hmqowtEIKAYBiVr1DNEBAftXsL+ibD4Z+36IEkUke8nGP/VKnGJVS7fYLTpc/rBjBCEhj RW1cFDQD5p7MBbyXRmHlQi3f/B9r6z1wRe5cwv0NkYyKi1w0xeirUtJi+6tXbDLx1nTF3N3FJ dtSqr3BKBcC4/XmamjJqQDa0P4qjoZ/1h33ny48yahjP+taxPR5DMq341fY4CWa7kDtBzPKj1 suAAM3N Received-SPF: permerror client-ip=212.227.126.135; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" As qemu_opts_parse_noisily() flattens the QAPI structures ("type" field of Netdev structure can collides with "type" field of SocketAddress), we introduce a way to bypass qemu_opts_parse_noisily() and use directly visit_type_Netdev() to parse the backend parameters. More details from Markus: qemu_init() passes the argument of -netdev, -nic, and -net to net_client_parse(). net_client_parse() parses with qemu_opts_parse_noisily(), passing QemuOptsList qemu_netdev_opts for -netdev, qemu_nic_opts for -nic, and qemu_net_opts for -net. Their desc[] are all empty, which means any keys are accepted. The result of the parse (a QemuOpts) is stored in the QemuOptsList. Note that QemuOpts is flat by design. In some places, we layer non-flat on top using dotted keys convention, but not here. net_init_clients() iterates over the stored QemuOpts, and passes them to net_init_netdev(), net_param_nic(), or net_init_client(), respectively. These functions pass the QemuOpts to net_client_init(). They also do other things with the QemuOpts, which we can ignore here. net_client_init() uses the opts visitor to convert the (flat) QemOpts to a (non-flat) QAPI object Netdev. Netdev is also the argument of QMP command netdev_add. The opts visitor was an early attempt to support QAPI in (QemuOpts-based) CLI. It restricts QAPI types to a certain shape; see commit eb7ee2cbeb "qapi: introduce OptsVisitor". A more modern way to support QAPI is qobject_input_visitor_new_str(). It uses keyval_parse() instead of QemuOpts for KEY=VALUE,... syntax, and it also supports JSON syntax. The former isn't quite as expressive as JSON, but it's a lot closer than QemuOpts + opts visitor. This commit paves the way to use of the modern way instead. Signed-off-by: Laurent Vivier Reviewed-by: Markus Armbruster Acked-by: Michael S. Tsirkin --- include/net/net.h | 2 ++ net/net.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ softmmu/vl.c | 6 ++++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/include/net/net.h b/include/net/net.h index 55023e7e9fa9..025dbf1e143b 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -220,6 +220,8 @@ extern NICInfo nd_table[MAX_NICS]; extern const char *host_net_devices[]; /* from net.c */ +bool netdev_is_modern(const char *optarg); +void netdev_parse_modern(const char *optarg); void net_client_parse(QemuOptsList *opts_list, const char *str); void show_netdevs(void); void net_init_clients(void); diff --git a/net/net.c b/net/net.c index f056e8aebfb2..ffe3e5a2cf1d 100644 --- a/net/net.c +++ b/net/net.c @@ -54,6 +54,7 @@ #include "net/colo-compare.h" #include "net/filter.h" #include "qapi/string-output-visitor.h" +#include "qapi/qobject-input-visitor.h" /* Net bridge is currently not supported for W32. */ #if !defined(_WIN32) @@ -63,6 +64,16 @@ static VMChangeStateEntry *net_change_state_entry; static QTAILQ_HEAD(, NetClientState) net_clients; +typedef struct NetdevQueueEntry { + Netdev *nd; + Location loc; + QSIMPLEQ_ENTRY(NetdevQueueEntry) entry; +} NetdevQueueEntry; + +typedef QSIMPLEQ_HEAD(, NetdevQueueEntry) NetdevQueue; + +static NetdevQueue nd_queue = QSIMPLEQ_HEAD_INITIALIZER(nd_queue); + /***********************************************************/ /* network device redirectors */ @@ -1562,6 +1573,20 @@ out: return ret; } +static void netdev_init_modern(void) +{ + while (!QSIMPLEQ_EMPTY(&nd_queue)) { + NetdevQueueEntry *nd = QSIMPLEQ_FIRST(&nd_queue); + + QSIMPLEQ_REMOVE_HEAD(&nd_queue, entry); + loc_push_restore(&nd->loc); + net_client_init1(nd->nd, true, &error_fatal); + loc_pop(&nd->loc); + qapi_free_Netdev(nd->nd); + g_free(nd); + } +} + void net_init_clients(void) { net_change_state_entry = @@ -1569,6 +1594,8 @@ void net_init_clients(void) QTAILQ_INIT(&net_clients); + netdev_init_modern(); + qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, &error_fatal); @@ -1579,6 +1606,36 @@ void net_init_clients(void) &error_fatal); } +/* + * Does this -netdev argument use modern rather than traditional syntax? + * Modern syntax is to be parsed with netdev_parse_modern(). + * Traditional syntax is to be parsed with net_client_parse(). + */ +bool netdev_is_modern(const char *optarg) +{ + return false; +} + +/* + * netdev_parse_modern() uses modern, more expressive syntax than + * net_client_parse(), but supports only the -netdev option. + * netdev_parse_modern() appends to @nd_queue, whereas net_client_parse() + * appends to @qemu_netdev_opts. + */ +void netdev_parse_modern(const char *optarg) +{ + Visitor *v; + NetdevQueueEntry *nd; + + v = qobject_input_visitor_new_str(optarg, "type", &error_fatal); + nd = g_new(NetdevQueueEntry, 1); + visit_type_Netdev(v, NULL, &nd->nd, &error_fatal); + visit_free(v); + loc_save(&nd->loc); + + QSIMPLEQ_INSERT_TAIL(&nd_queue, nd, entry); +} + void net_client_parse(QemuOptsList *opts_list, const char *optarg) { if (!qemu_opts_parse_noisily(opts_list, optarg, true)) { diff --git a/softmmu/vl.c b/softmmu/vl.c index e69aa43de469..99fb49c7b0ee 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2801,7 +2801,11 @@ void qemu_init(int argc, char **argv) break; case QEMU_OPTION_netdev: default_net = 0; - net_client_parse(qemu_find_opts("netdev"), optarg); + if (netdev_is_modern(optarg)) { + netdev_parse_modern(optarg); + } else { + net_client_parse(qemu_find_opts("netdev"), optarg); + } break; case QEMU_OPTION_nic: default_net = 0; From patchwork Tue Oct 11 20:05:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004318 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 CEF19C433FE for ; Tue, 11 Oct 2022 20:25:15 +0000 (UTC) Received: from localhost ([::1]:53142 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLoP-0004gK-TP for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:25:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55050) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVx-0006PO-L0 for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:15 -0400 Received: from mout.kundenserver.de ([212.227.126.135]:33799) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVv-0003km-0E for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:09 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MzR0i-1p49gF2jg0-00vN3s; Tue, 11 Oct 2022 22:05:51 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org Subject: [PATCH v11 05/17] net: introduce qemu_set_info_str() function Date: Tue, 11 Oct 2022 22:05:27 +0200 Message-Id: <20221011200539.1486809-6-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:0DB2EvkFlagqxOpD6HAXmRry2h+vrL4EUeB/KaCoTBpM8WeRL5s b04OIAzy12waWl3G/SKIDGcxJPSFeO/jU3WHh6Xmn3fd9SQYacMnSVfTQBehrLSeGKl/VXu tzDfTBaD/akQNurGwAZB+s01lbQZ9FofBG/GUkTNXQxjLjdbHV7OLf5xGj+d04FCB2A0lRm K/VxV1Rs5nwa/TZQuovLA== X-UI-Out-Filterresults: notjunk:1;V03:K0:o6RepLgEkd0=:YQM5XIqUXRFl7NDz4KbiV0 goitypBU5hH9J2V+UKrzfglEaXYDKSvnaIoTKkbLhgwkgaKTE+iuoRal3vGu2KF2GR0dzkjrJ thbvH2W+SP1mNb9QCNbUsliHoMXVnFDddQIvYy4Y22DfdIQynM56nPS8VptJpHHJekkzb7LQW Z2sNQDGYYvL2JkJQlho4ZfAjudpy7z5qN7NODPDC6notUG8ZyhjdUwUKi2nylpGVPFFwthzGD LgZvVv7v9HFcesG8+kG4I6M2ifcJuqQjC4QCKWwDRAZgKq642iAHg/2wF8HqX990LgMDDuTwV ypplw7Skjfee812VrTsgKfuk0zC3DT4SJxfLqYXxLX4HI/9EcWmuL7MZrXHfL2EDU+tASwcwe NbNe6wt6s1Uhi95ZjpAa5ccpVtQLTewy7bVKFi+jl9zvJOtx+GDpin0rV67xP8KNhtxln5is2 /XyROwWMQYhhQgYb2kyS1dB11mZ50aXw1+cxeaItrGv15C5wg6DgSWq7P1uYOmG+g/hyzmoeN 4tCccPUphz9lDXhXv3UQVCMbGfruu05xQCzJlsTnlCa7LmZ4LER11lTxhWRtlTf+quOb47eKv DoBrHpO67De+7Q2l66ved6YLbEjlOh9xP/xhMtk1NCnV1VOyBSJEIsWXW65zKTdQNWrTBprhP bZ90i27bPBebuV/IjpPF9dnq7LHDsxIE3mYqws2B2+eCJ0Nqo7/6LwPo6PquX1ysbO7OA+irc wGmMJGY8lEf/zSTr81+O2SKGzQSR6YHgNNG2aco3MDLmKq3u48NiFcRieJo/B+qKwtpG770KE QbMMCk9 Received-SPF: permerror client-ip=212.227.126.135; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" Embed the setting of info_str in a function. Signed-off-by: Laurent Vivier Reviewed-by: David Gibson Acked-by: Michael S. Tsirkin --- hw/net/xen_nic.c | 5 ++--- include/net/net.h | 1 + net/l2tpv3.c | 3 +-- net/net.c | 17 ++++++++++++----- net/slirp.c | 5 ++--- net/socket.c | 33 ++++++++++++++------------------- net/tap-win32.c | 3 +-- net/tap.c | 13 +++++-------- net/vde.c | 3 +-- net/vhost-user.c | 3 +-- net/vhost-vdpa.c | 2 +- 11 files changed, 41 insertions(+), 47 deletions(-) diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c index 5c815b4f0c52..7d92c2d022b0 100644 --- a/hw/net/xen_nic.c +++ b/hw/net/xen_nic.c @@ -296,9 +296,8 @@ static int net_init(struct XenLegacyDevice *xendev) netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf, "xen", NULL, netdev); - snprintf(qemu_get_queue(netdev->nic)->info_str, - sizeof(qemu_get_queue(netdev->nic)->info_str), - "nic: xenbus vif macaddr=%s", netdev->mac); + qemu_set_info_str(qemu_get_queue(netdev->nic), + "nic: xenbus vif macaddr=%s", netdev->mac); /* fill info */ xenstore_write_be_int(&netdev->xendev, "feature-rx-copy", 1); diff --git a/include/net/net.h b/include/net/net.h index 025dbf1e143b..3db75ff841ff 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -177,6 +177,7 @@ ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf, void qemu_purge_queued_packets(NetClientState *nc); void qemu_flush_queued_packets(NetClientState *nc); void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge); +void qemu_set_info_str(NetClientState *nc, const char *fmt, ...); void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6]); bool qemu_has_ufo(NetClientState *nc); bool qemu_has_vnet_hdr(NetClientState *nc); diff --git a/net/l2tpv3.c b/net/l2tpv3.c index af373e5c300c..350041a0d6c0 100644 --- a/net/l2tpv3.c +++ b/net/l2tpv3.c @@ -723,8 +723,7 @@ int net_init_l2tpv3(const Netdev *netdev, l2tpv3_read_poll(s, true); - snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "l2tpv3: connected"); + qemu_set_info_str(&s->nc, "l2tpv3: connected"); return 0; outerr: qemu_del_net_client(nc); diff --git a/net/net.c b/net/net.c index ffe3e5a2cf1d..41e05137d431 100644 --- a/net/net.c +++ b/net/net.c @@ -141,13 +141,20 @@ char *qemu_mac_strdup_printf(const uint8_t *macaddr) macaddr[3], macaddr[4], macaddr[5]); } +void qemu_set_info_str(NetClientState *nc, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsnprintf(nc->info_str, sizeof(nc->info_str), fmt, ap); + va_end(ap); +} + void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6]) { - snprintf(nc->info_str, sizeof(nc->info_str), - "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x", - nc->model, - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); + qemu_set_info_str(nc, "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x", + nc->model, macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); } static int mac_table[256] = {0}; diff --git a/net/slirp.c b/net/slirp.c index 8679be644420..14a8d592774c 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -611,9 +611,8 @@ static int net_slirp_init(NetClientState *peer, const char *model, nc = qemu_new_net_client(&net_slirp_info, peer, model, name); - snprintf(nc->info_str, sizeof(nc->info_str), - "net=%s,restrict=%s", inet_ntoa(net), - restricted ? "on" : "off"); + qemu_set_info_str(nc, "net=%s,restrict=%s", inet_ntoa(net), + restricted ? "on" : "off"); s = DO_UPCAST(SlirpState, nc, nc); diff --git a/net/socket.c b/net/socket.c index bfd8596250c4..ade1ecf38b87 100644 --- a/net/socket.c +++ b/net/socket.c @@ -179,7 +179,7 @@ static void net_socket_send(void *opaque) s->fd = -1; net_socket_rs_init(&s->rs, net_socket_rs_finalize, false); s->nc.link_down = true; - memset(s->nc.info_str, 0, sizeof(s->nc.info_str)); + qemu_set_info_str(&s->nc, ""); return; } @@ -387,16 +387,15 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, /* mcast: save bound address as dst */ if (is_connected && mcast != NULL) { s->dgram_dst = saddr; - snprintf(nc->info_str, sizeof(nc->info_str), - "socket: fd=%d (cloned mcast=%s:%d)", - fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); + qemu_set_info_str(nc, "socket: fd=%d (cloned mcast=%s:%d)", fd, + inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); } else { if (sa_type == SOCKET_ADDRESS_TYPE_UNIX) { s->dgram_dst.sin_family = AF_UNIX; } - snprintf(nc->info_str, sizeof(nc->info_str), - "socket: fd=%d %s", fd, SocketAddressType_str(sa_type)); + qemu_set_info_str(nc, "socket: fd=%d %s", fd, + SocketAddressType_str(sa_type)); } return s; @@ -430,7 +429,7 @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer, nc = qemu_new_net_client(&net_socket_info, peer, model, name); - snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd); + qemu_set_info_str(nc, "socket: fd=%d", fd); s = DO_UPCAST(NetSocketState, nc, nc); @@ -497,9 +496,8 @@ static void net_socket_accept(void *opaque) s->fd = fd; s->nc.link_down = false; net_socket_connect(s); - snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "socket: connection from %s:%d", - inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); + qemu_set_info_str(&s->nc, "socket: connection from %s:%d", + inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); } static int net_socket_listen_init(NetClientState *peer, @@ -597,9 +595,8 @@ static int net_socket_connect_init(NetClientState *peer, return -1; } - snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "socket: connect to %s:%d", - inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); + qemu_set_info_str(&s->nc, "socket: connect to %s:%d", + inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return 0; } @@ -642,9 +639,8 @@ static int net_socket_mcast_init(NetClientState *peer, s->dgram_dst = saddr; - snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "socket: mcast=%s:%d", - inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); + qemu_set_info_str(&s->nc, "socket: mcast=%s:%d", + inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return 0; } @@ -697,9 +693,8 @@ static int net_socket_udp_init(NetClientState *peer, s->dgram_dst = raddr; - snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "socket: udp=%s:%d", - inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port)); + qemu_set_info_str(&s->nc, "socket: udp=%s:%d", inet_ntoa(raddr.sin_addr), + ntohs(raddr.sin_port)); return 0; } diff --git a/net/tap-win32.c b/net/tap-win32.c index 7466f22e77a4..a49c28ba5dc5 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -789,8 +789,7 @@ static int tap_win32_init(NetClientState *peer, const char *model, s = DO_UPCAST(TAPState, nc, nc); - snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "tap: ifname=%s", ifname); + qemu_set_info_str(&s->nc, "tap: ifname=%s", ifname); s->handle = handle; diff --git a/net/tap.c b/net/tap.c index e203d07a1216..1210a0436de8 100644 --- a/net/tap.c +++ b/net/tap.c @@ -630,8 +630,7 @@ int net_init_bridge(const Netdev *netdev, const char *name, } s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr); - snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s", helper, - br); + qemu_set_info_str(&s->nc, "helper=%s,br=%s", helper, br); return 0; } @@ -690,14 +689,12 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, } if (tap->has_fd || tap->has_fds) { - snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd); + qemu_set_info_str(&s->nc, "fd=%d", fd); } else if (tap->has_helper) { - snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s", - tap->helper); + qemu_set_info_str(&s->nc, "helper=%s", tap->helper); } else { - snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "ifname=%s,script=%s,downscript=%s", ifname, script, - downscript); + qemu_set_info_str(&s->nc, "ifname=%s,script=%s,downscript=%s", ifname, + script, downscript); if (strcmp(downscript, "no") != 0) { snprintf(s->down_script, sizeof(s->down_script), "%s", downscript); diff --git a/net/vde.c b/net/vde.c index 1083916bcf52..c0a08662cc30 100644 --- a/net/vde.c +++ b/net/vde.c @@ -98,8 +98,7 @@ static int net_vde_init(NetClientState *peer, const char *model, nc = qemu_new_net_client(&net_vde_info, peer, model, name); - snprintf(nc->info_str, sizeof(nc->info_str), "sock=%s,fd=%d", - sock, vde_datafd(vde)); + qemu_set_info_str(nc, "sock=%s,fd=%d", sock, vde_datafd(vde)); s = DO_UPCAST(VDEState, nc, nc); diff --git a/net/vhost-user.c b/net/vhost-user.c index b1a0247b5981..3a6b90da8661 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -341,8 +341,7 @@ static int net_vhost_user_init(NetClientState *peer, const char *device, user = g_new0(struct VhostUserState, 1); for (i = 0; i < queues; i++) { nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name); - snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s", - i, chr->label); + qemu_set_info_str(nc, "vhost-user%d to %s", i, chr->label); nc->queue_index = i; if (!nc0) { nc0 = nc; diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 4bc3fd01a878..e1865bea6aa3 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -593,7 +593,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, nc = qemu_new_net_control_client(&net_vhost_vdpa_cvq_info, peer, device, name); } - snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA); + qemu_set_info_str(nc, TYPE_VHOST_VDPA); s = DO_UPCAST(VhostVDPAState, nc, nc); s->vhost_vdpa.device_fd = vdpa_device_fd; From patchwork Tue Oct 11 20:05:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004308 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 439F3C43217 for ; Tue, 11 Oct 2022 20:09:40 +0000 (UTC) Received: from localhost ([::1]:40048 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLZL-0000sE-5o for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:09:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55062) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLW1-0006Pj-SF for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:20 -0400 Received: from mout.kundenserver.de ([212.227.126.134]:52105) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVu-0003kp-W8 for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:12 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N1g3U-1pAlNx0owK-011xiW; Tue, 11 Oct 2022 22:05:54 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org, Stefano Brivio Subject: [PATCH v11 06/17] qapi: net: add stream and dgram netdevs Date: Tue, 11 Oct 2022 22:05:28 +0200 Message-Id: <20221011200539.1486809-7-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:fO2WOE1biiJie56d9Sb6kJcOn10Tu5f82bI2b+cyRMG37JRU/PM qZC4weFbBZ0hOSGDMHNK4WIOw/VmRh9zsrY60UTq+hlHGpgPobJujNuH+P/vyXf8w8kRyfh x5p7gDgTV5VgQM4bjBFmppcek9YBewsriN4t0NNbBduCaDR1/O3wigVj8DoSnt4VnSwCY/7 8xXEJWZ/vSu22HnpXy/Ag== X-UI-Out-Filterresults: notjunk:1;V03:K0:NRnRuWPjzEQ=:H4FPHafxY+LYt11196Quqr P8qPX2rmcSkeqhbiKXCKZraA9pn9oDqpBl24fPWuDfT0lg6PFMaHri7o4E2CHnMguAsA1AWEQ Jkt6coNexnpJFH4vhf3LkIkhOEZYZQkPrysrIhC43Sj9tenv5U+T8WjtlJEE3IMk8oTEz1Ba7 14ZUKZgD1+xfPYeDvojofLgut3qXr8PCAWc4D4qM6jCswijCI1jM0JzMf0JnW/glvp+hdQLRf xrqVmi+beTrWqdEyVI9Dry3jJjToilrGKU2i6Wvy7bxmdkLqc1+pPbKJBxz8N463V8NS0LWiu ShimYTv43JTuhCguLerU2nO8i2ZIUVHbJXQroa2BNUqG9px59UUHO926qt4wXBLfScIouZnfd 8gx1E921PCMgJQx9H0CgEbsmLXluHJ1ql81cfMB3IvvA1eGZbw4G1RoRYGKG0HRCVBRrMleko HFhGXYgK2ybXBN66mIJEEAOs+ZKNEHVOy3NS0PwvrZR61A7xUtaXGNysVBAtW+DLPD1Y3Eu4s MMYWY7yrvV4kL8733cIshdHjp1KMkng5z9ukLFJj6c00dhmeNDEpMC+xqaKDkCu1MO4aYHuZo spqNJJ3YxhPmbDBUmnheVIrAFmRvY49s6OrIUWD1FCN+n0Wh0cYNMnWh8wdHaHVkBvZoi7ZDs rMT+NfK9Fs4pHvc/WTWQQZnYnU/dku+EdBuQgDBFrSpe2GDgNw/qIkmJfqzxO3xh5s0yrVNW8 a96f3YAGAXed6+eAdh9++k7jfkLKIeNIn6iVJfz26R0fRojlxluSM/TdpVh9GQafr1qz3WPVg v8r4tQa Received-SPF: permerror client-ip=212.227.126.134; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" Copied from socket netdev file and modified to use SocketAddress to be able to introduce new features like unix socket. "udp" and "mcast" are squashed into dgram netdev, multicast is detected according to the IP address type. "listen" and "connect" modes are managed by stream netdev. An optional parameter "server" defines the mode (server by default) The two new types need to be parsed the modern way with -netdev, because with the traditional way, the "type" field of netdev structure collides with the "type" field of SocketAddress and prevents the correct evaluation of the command line option. Moreover the traditional way doesn't allow to use the same type (SocketAddress) several times with the -netdev option (needed to specify "local" and "remote" addresses). The previous commit paved the way for parsing the modern way, but omitted one detail: how to pick modern vs. traditional, in netdev_is_modern(). We want to pick based on the value of parameter "type". But how to extract it from the option argument? Parsing the option argument, either the modern or the traditional way, extracts it for us, but only if parsing succeeds. If parsing fails, there is no good option. No matter which parser we pick, it'll be the wrong one for some arguments, and the error reporting will be confusing. Fortunately, the traditional parser accepts *anything* when called in a certain way. This maximizes our chance to extract the value of "type", and in turn minimizes the risk of confusing error reporting. Signed-off-by: Laurent Vivier Reviewed-by: Stefano Brivio Acked-by: Markus Armbruster Acked-by: Michael S. Tsirkin --- hmp-commands.hx | 2 +- net/clients.h | 6 + net/dgram.c | 537 ++++++++++++++++++++++++++++++++++++++++++++++++ net/hub.c | 2 + net/meson.build | 2 + net/net.c | 30 ++- net/stream.c | 425 ++++++++++++++++++++++++++++++++++++++ qapi/net.json | 66 +++++- qemu-options.hx | 12 ++ 9 files changed, 1078 insertions(+), 4 deletions(-) create mode 100644 net/dgram.c create mode 100644 net/stream.c diff --git a/hmp-commands.hx b/hmp-commands.hx index 8ab8000acd9e..da40a7eb04ed 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1276,7 +1276,7 @@ ERST { .name = "netdev_add", .args_type = "netdev:O", - .params = "[user|tap|socket|vde|bridge|hubport|netmap|vhost-user" + .params = "[user|tap|socket|stream|dgram|vde|bridge|hubport|netmap|vhost-user" #ifdef CONFIG_VMNET "|vmnet-host|vmnet-shared|vmnet-bridged" #endif diff --git a/net/clients.h b/net/clients.h index c9157789f2ce..ed8bdfff1e7c 100644 --- a/net/clients.h +++ b/net/clients.h @@ -40,6 +40,12 @@ int net_init_hubport(const Netdev *netdev, const char *name, int net_init_socket(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp); +int net_init_stream(const Netdev *netdev, const char *name, + NetClientState *peer, Error **errp); + +int net_init_dgram(const Netdev *netdev, const char *name, + NetClientState *peer, Error **errp); + int net_init_tap(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp); diff --git a/net/dgram.c b/net/dgram.c new file mode 100644 index 000000000000..5339585b8202 --- /dev/null +++ b/net/dgram.c @@ -0,0 +1,537 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2022 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" + +#include "net/net.h" +#include "clients.h" +#include "monitor/monitor.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/option.h" +#include "qemu/sockets.h" +#include "qemu/iov.h" +#include "qemu/main-loop.h" +#include "qemu/cutils.h" + +typedef struct NetDgramState { + NetClientState nc; + int fd; + SocketReadState rs; + struct sockaddr_in dgram_dst; /* contains destination iff connectionless */ + bool read_poll; /* waiting to receive data? */ + bool write_poll; /* waiting to transmit data? */ +} NetDgramState; + +static void net_dgram_send(void *opaque); +static void net_dgram_writable(void *opaque); + +static void net_dgram_update_fd_handler(NetDgramState *s) +{ + qemu_set_fd_handler(s->fd, + s->read_poll ? net_dgram_send : NULL, + s->write_poll ? net_dgram_writable : NULL, + s); +} + +static void net_dgram_read_poll(NetDgramState *s, bool enable) +{ + s->read_poll = enable; + net_dgram_update_fd_handler(s); +} + +static void net_dgram_write_poll(NetDgramState *s, bool enable) +{ + s->write_poll = enable; + net_dgram_update_fd_handler(s); +} + +static void net_dgram_writable(void *opaque) +{ + NetDgramState *s = opaque; + + net_dgram_write_poll(s, false); + + qemu_flush_queued_packets(&s->nc); +} + +static ssize_t net_dgram_receive(NetClientState *nc, + const uint8_t *buf, size_t size) +{ + NetDgramState *s = DO_UPCAST(NetDgramState, nc, nc); + ssize_t ret; + + do { + if (s->dgram_dst.sin_family != AF_UNIX) { + ret = sendto(s->fd, buf, size, 0, + (struct sockaddr *)&s->dgram_dst, + sizeof(s->dgram_dst)); + } else { + ret = send(s->fd, buf, size, 0); + } + } while (ret == -1 && errno == EINTR); + + if (ret == -1 && errno == EAGAIN) { + net_dgram_write_poll(s, true); + return 0; + } + return ret; +} + +static void net_dgram_send_completed(NetClientState *nc, ssize_t len) +{ + NetDgramState *s = DO_UPCAST(NetDgramState, nc, nc); + + if (!s->read_poll) { + net_dgram_read_poll(s, true); + } +} + +static void net_dgram_rs_finalize(SocketReadState *rs) +{ + NetDgramState *s = container_of(rs, NetDgramState, rs); + + if (qemu_send_packet_async(&s->nc, rs->buf, + rs->packet_len, + net_dgram_send_completed) == 0) { + net_dgram_read_poll(s, false); + } +} + +static void net_dgram_send(void *opaque) +{ + NetDgramState *s = opaque; + int size; + + size = recv(s->fd, s->rs.buf, sizeof(s->rs.buf), 0); + if (size < 0) { + return; + } + if (size == 0) { + /* end of connection */ + net_dgram_read_poll(s, false); + net_dgram_write_poll(s, false); + return; + } + if (qemu_send_packet_async(&s->nc, s->rs.buf, size, + net_dgram_send_completed) == 0) { + net_dgram_read_poll(s, false); + } +} + +static int net_dgram_mcast_create(struct sockaddr_in *mcastaddr, + struct in_addr *localaddr, + Error **errp) +{ + struct ip_mreq imr; + int fd; + int val, ret; +#ifdef __OpenBSD__ + unsigned char loop; +#else + int loop; +#endif + + if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) { + error_setg(errp, "specified mcastaddr %s (0x%08x) " + "does not contain a multicast address", + inet_ntoa(mcastaddr->sin_addr), + (int)ntohl(mcastaddr->sin_addr.s_addr)); + return -1; + } + + fd = qemu_socket(PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + error_setg_errno(errp, errno, "can't create datagram socket"); + return -1; + } + + /* + * Allow multiple sockets to bind the same multicast ip and port by setting + * SO_REUSEADDR. This is the only situation where SO_REUSEADDR should be set + * on windows. Use socket_set_fast_reuse otherwise as it sets SO_REUSEADDR + * only on posix systems. + */ + val = 1; + ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + if (ret < 0) { + error_setg_errno(errp, errno, "can't set socket option SO_REUSEADDR"); + goto fail; + } + + ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr)); + if (ret < 0) { + error_setg_errno(errp, errno, "can't bind ip=%s to socket", + inet_ntoa(mcastaddr->sin_addr)); + goto fail; + } + + /* Add host to multicast group */ + imr.imr_multiaddr = mcastaddr->sin_addr; + if (localaddr) { + imr.imr_interface = *localaddr; + } else { + imr.imr_interface.s_addr = htonl(INADDR_ANY); + } + + ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + &imr, sizeof(struct ip_mreq)); + if (ret < 0) { + error_setg_errno(errp, errno, + "can't add socket to multicast group %s", + inet_ntoa(imr.imr_multiaddr)); + goto fail; + } + + /* Force mcast msgs to loopback (eg. several QEMUs in same host */ + loop = 1; + ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, + &loop, sizeof(loop)); + if (ret < 0) { + error_setg_errno(errp, errno, + "can't force multicast message to loopback"); + goto fail; + } + + /* If a bind address is given, only send packets from that address */ + if (localaddr != NULL) { + ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + localaddr, sizeof(*localaddr)); + if (ret < 0) { + error_setg_errno(errp, errno, + "can't set the default network send interface"); + goto fail; + } + } + + qemu_socket_set_nonblock(fd); + return fd; +fail: + if (fd >= 0) { + closesocket(fd); + } + return -1; +} + +static void net_dgram_cleanup(NetClientState *nc) +{ + NetDgramState *s = DO_UPCAST(NetDgramState, nc, nc); + if (s->fd != -1) { + net_dgram_read_poll(s, false); + net_dgram_write_poll(s, false); + close(s->fd); + s->fd = -1; + } +} + +static NetClientInfo net_dgram_socket_info = { + .type = NET_CLIENT_DRIVER_DGRAM, + .size = sizeof(NetDgramState), + .receive = net_dgram_receive, + .cleanup = net_dgram_cleanup, +}; + +static NetDgramState *net_dgram_fd_init(NetClientState *peer, + const char *model, + const char *name, + int fd, int is_fd, + SocketAddress *mcast, + Error **errp) +{ + struct sockaddr_in saddr; + int newfd; + NetClientState *nc; + NetDgramState *s; + SocketAddress *sa; + SocketAddressType sa_type; + + sa = socket_local_address(fd, errp); + if (!sa) { + return NULL; + } + sa_type = sa->type; + qapi_free_SocketAddress(sa); + + /* + * fd passed: multicast: "learn" dgram_dst address from bound address and + * save it. Because this may be "shared" socket from a "master" process, + * datagrams would be recv() by ONLY ONE process: we must "clone" this + * dgram socket --jjo + */ + + if (is_fd && mcast != NULL) { + if (convert_host_port(&saddr, mcast->u.inet.host, + mcast->u.inet.port, errp) < 0) { + goto err; + } + /* must be bound */ + if (saddr.sin_addr.s_addr == 0) { + error_setg(errp, "can't setup multicast destination address"); + goto err; + } + /* clone dgram socket */ + newfd = net_dgram_mcast_create(&saddr, NULL, errp); + if (newfd < 0) { + goto err; + } + /* clone newfd to fd, close newfd */ + dup2(newfd, fd); + close(newfd); + + } + + nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name); + + s = DO_UPCAST(NetDgramState, nc, nc); + + s->fd = fd; + net_socket_rs_init(&s->rs, net_dgram_rs_finalize, false); + net_dgram_read_poll(s, true); + + /* mcast: save bound address as dst */ + if (is_fd && mcast != NULL) { + s->dgram_dst = saddr; + qemu_set_info_str(nc, "fd=%d (cloned mcast=%s:%d)", fd, + inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); + } else { + if (sa_type == SOCKET_ADDRESS_TYPE_UNIX) { + s->dgram_dst.sin_family = AF_UNIX; + } + + qemu_set_info_str(nc, "fd=%d %s", fd, SocketAddressType_str(sa_type)); + } + + return s; + +err: + closesocket(fd); + return NULL; +} + +static int net_dgram_mcast_init(NetClientState *peer, + const char *model, + const char *name, + SocketAddress *remote, + SocketAddress *local, + Error **errp) +{ + NetDgramState *s; + int fd, ret; + struct sockaddr_in saddr; + + if (remote->type != SOCKET_ADDRESS_TYPE_INET) { + error_setg(errp, "multicast only support inet type"); + return -1; + } + + if (convert_host_port(&saddr, remote->u.inet.host, remote->u.inet.port, + errp) < 0) { + return -1; + } + + if (!local) { + fd = net_dgram_mcast_create(&saddr, NULL, errp); + if (fd < 0) { + return -1; + } + } else { + switch (local->type) { + case SOCKET_ADDRESS_TYPE_INET: { + struct in_addr localaddr; + + if (inet_aton(local->u.inet.host, &localaddr) == 0) { + error_setg(errp, "localaddr '%s' is not a valid IPv4 address", + local->u.inet.host); + return -1; + } + + fd = net_dgram_mcast_create(&saddr, &localaddr, errp); + if (fd < 0) { + return -1; + } + break; + } + case SOCKET_ADDRESS_TYPE_FD: + fd = monitor_fd_param(monitor_cur(), local->u.fd.str, errp); + if (fd == -1) { + return -1; + } + ret = qemu_socket_try_set_nonblock(fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + return -1; + } + break; + default: + error_setg(errp, "only support inet or fd type for local"); + return -1; + } + } + + s = net_dgram_fd_init(peer, model, name, fd, + local->type == SOCKET_ADDRESS_TYPE_FD, + remote, errp); + if (!s) { + return -1; + } + + s->dgram_dst = saddr; + + qemu_set_info_str(&s->nc, "mcast=%s:%d", inet_ntoa(saddr.sin_addr), + ntohs(saddr.sin_port)); + return 0; + +} + + +int net_init_dgram(const Netdev *netdev, const char *name, + NetClientState *peer, Error **errp) +{ + NetDgramState *s; + int fd, ret; + struct sockaddr_in raddr_in; + struct sockaddr_in laddr_in; + SocketAddress *remote, *local; + + assert(netdev->type == NET_CLIENT_DRIVER_DGRAM); + + remote = netdev->u.dgram.remote; + local = netdev->u.dgram.local; + + /* detect multicast address */ + if (remote && remote->type == SOCKET_ADDRESS_TYPE_INET) { + struct sockaddr_in mcastaddr; + + if (convert_host_port(&mcastaddr, remote->u.inet.host, + remote->u.inet.port, errp) < 0) { + return -1; + } + + if (IN_MULTICAST(ntohl(mcastaddr.sin_addr.s_addr))) { + return net_dgram_mcast_init(peer, "dram", name, remote, local, + errp); + } + } + + /* unicast address */ + if (!local) { + error_setg(errp, "dgram requires local= parameter"); + return -1; + } + + if (remote) { + if (local->type == SOCKET_ADDRESS_TYPE_FD) { + error_setg(errp, "don't set remote with local.fd"); + return -1; + } + if (remote->type != local->type) { + error_setg(errp, "remote and local types must be the same"); + return -1; + } + } else { + if (local->type != SOCKET_ADDRESS_TYPE_FD) { + error_setg(errp, "type=inet requires remote parameter"); + return -1; + } + } + + switch (local->type) { + case SOCKET_ADDRESS_TYPE_INET: + if (convert_host_port(&laddr_in, local->u.inet.host, local->u.inet.port, + errp) < 0) { + return -1; + } + + if (convert_host_port(&raddr_in, remote->u.inet.host, + remote->u.inet.port, errp) < 0) { + return -1; + } + + fd = qemu_socket(PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + error_setg_errno(errp, errno, "can't create datagram socket"); + return -1; + } + + ret = socket_set_fast_reuse(fd); + if (ret < 0) { + error_setg_errno(errp, errno, + "can't set socket option SO_REUSEADDR"); + closesocket(fd); + return -1; + } + ret = bind(fd, (struct sockaddr *)&laddr_in, sizeof(laddr_in)); + if (ret < 0) { + error_setg_errno(errp, errno, "can't bind ip=%s to socket", + inet_ntoa(laddr_in.sin_addr)); + closesocket(fd); + return -1; + } + qemu_socket_set_nonblock(fd); + break; + case SOCKET_ADDRESS_TYPE_FD: + fd = monitor_fd_param(monitor_cur(), local->u.fd.str, errp); + if (fd == -1) { + return -1; + } + ret = qemu_socket_try_set_nonblock(fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + return -1; + } + break; + default: + error_setg(errp, "only support inet or fd type for local"); + return -1; + } + + s = net_dgram_fd_init(peer, "dgram", name, fd, 0, NULL, errp); + if (!s) { + return -1; + } + + if (remote) { + s->dgram_dst = raddr_in; + } + + switch (local->type) { + case SOCKET_ADDRESS_TYPE_INET: + qemu_set_info_str(&s->nc, "udp=%s:%d/%s:%d", + inet_ntoa(laddr_in.sin_addr), + ntohs(laddr_in.sin_port), + inet_ntoa(raddr_in.sin_addr), + ntohs(raddr_in.sin_port)); + break; + case SOCKET_ADDRESS_TYPE_FD: + qemu_set_info_str(&s->nc, "fd=%d", fd); + break; + default: + g_assert_not_reached(); + } + + return 0; +} diff --git a/net/hub.c b/net/hub.c index 1375738bf121..67ca53485638 100644 --- a/net/hub.c +++ b/net/hub.c @@ -313,6 +313,8 @@ void net_hub_check_clients(void) case NET_CLIENT_DRIVER_USER: case NET_CLIENT_DRIVER_TAP: case NET_CLIENT_DRIVER_SOCKET: + case NET_CLIENT_DRIVER_STREAM: + case NET_CLIENT_DRIVER_DGRAM: case NET_CLIENT_DRIVER_VDE: case NET_CLIENT_DRIVER_VHOST_USER: has_host_dev = 1; diff --git a/net/meson.build b/net/meson.build index d1be76daf361..6cd1e3dab3a6 100644 --- a/net/meson.build +++ b/net/meson.build @@ -13,6 +13,8 @@ softmmu_ss.add(files( 'net.c', 'queue.c', 'socket.c', + 'stream.c', + 'dgram.c', 'util.c', )) diff --git a/net/net.c b/net/net.c index 41e05137d431..dd063d71b7b3 100644 --- a/net/net.c +++ b/net/net.c @@ -48,6 +48,7 @@ #include "qemu/qemu-print.h" #include "qemu/main-loop.h" #include "qemu/option.h" +#include "qemu/keyval.h" #include "qapi/error.h" #include "qapi/opts-visitor.h" #include "sysemu/runstate.h" @@ -1021,6 +1022,8 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])( #endif [NET_CLIENT_DRIVER_TAP] = net_init_tap, [NET_CLIENT_DRIVER_SOCKET] = net_init_socket, + [NET_CLIENT_DRIVER_STREAM] = net_init_stream, + [NET_CLIENT_DRIVER_DGRAM] = net_init_dgram, #ifdef CONFIG_VDE [NET_CLIENT_DRIVER_VDE] = net_init_vde, #endif @@ -1108,6 +1111,8 @@ void show_netdevs(void) int idx; const char *available_netdevs[] = { "socket", + "stream", + "dgram", "hubport", "tap", #ifdef CONFIG_SLIRP @@ -1620,7 +1625,30 @@ void net_init_clients(void) */ bool netdev_is_modern(const char *optarg) { - return false; + QemuOpts *opts; + bool is_modern; + const char *type; + static QemuOptsList dummy_opts = { + .name = "netdev", + .implied_opt_name = "type", + .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head), + .desc = { { } }, + }; + + if (optarg[0] == '{') { + /* This is JSON, which means it's modern syntax */ + return true; + } + + opts = qemu_opts_create(&dummy_opts, NULL, false, &error_abort); + qemu_opts_do_parse(opts, optarg, dummy_opts.implied_opt_name, + &error_abort); + type = qemu_opt_get(opts, "type"); + is_modern = !g_strcmp0(type, "stream") || !g_strcmp0(type, "dgram"); + + qemu_opts_reset(&dummy_opts); + + return is_modern; } /* diff --git a/net/stream.c b/net/stream.c new file mode 100644 index 000000000000..37965eb74e1a --- /dev/null +++ b/net/stream.c @@ -0,0 +1,425 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2022 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" + +#include "net/net.h" +#include "clients.h" +#include "monitor/monitor.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/option.h" +#include "qemu/sockets.h" +#include "qemu/iov.h" +#include "qemu/main-loop.h" +#include "qemu/cutils.h" + +typedef struct NetStreamState { + NetClientState nc; + int listen_fd; + int fd; + SocketReadState rs; + unsigned int send_index; /* number of bytes sent*/ + bool read_poll; /* waiting to receive data? */ + bool write_poll; /* waiting to transmit data? */ +} NetStreamState; + +static void net_stream_send(void *opaque); +static void net_stream_accept(void *opaque); +static void net_stream_writable(void *opaque); + +static void net_stream_update_fd_handler(NetStreamState *s) +{ + qemu_set_fd_handler(s->fd, + s->read_poll ? net_stream_send : NULL, + s->write_poll ? net_stream_writable : NULL, + s); +} + +static void net_stream_read_poll(NetStreamState *s, bool enable) +{ + s->read_poll = enable; + net_stream_update_fd_handler(s); +} + +static void net_stream_write_poll(NetStreamState *s, bool enable) +{ + s->write_poll = enable; + net_stream_update_fd_handler(s); +} + +static void net_stream_writable(void *opaque) +{ + NetStreamState *s = opaque; + + net_stream_write_poll(s, false); + + qemu_flush_queued_packets(&s->nc); +} + +static ssize_t net_stream_receive(NetClientState *nc, const uint8_t *buf, + size_t size) +{ + NetStreamState *s = DO_UPCAST(NetStreamState, nc, nc); + uint32_t len = htonl(size); + struct iovec iov[] = { + { + .iov_base = &len, + .iov_len = sizeof(len), + }, { + .iov_base = (void *)buf, + .iov_len = size, + }, + }; + size_t remaining; + ssize_t ret; + + remaining = iov_size(iov, 2) - s->send_index; + ret = iov_send(s->fd, iov, 2, s->send_index, remaining); + + if (ret == -1 && errno == EAGAIN) { + ret = 0; /* handled further down */ + } + if (ret == -1) { + s->send_index = 0; + return -errno; + } + if (ret < (ssize_t)remaining) { + s->send_index += ret; + net_stream_write_poll(s, true); + return 0; + } + s->send_index = 0; + return size; +} + +static void net_stream_send_completed(NetClientState *nc, ssize_t len) +{ + NetStreamState *s = DO_UPCAST(NetStreamState, nc, nc); + + if (!s->read_poll) { + net_stream_read_poll(s, true); + } +} + +static void net_stream_rs_finalize(SocketReadState *rs) +{ + NetStreamState *s = container_of(rs, NetStreamState, rs); + + if (qemu_send_packet_async(&s->nc, rs->buf, + rs->packet_len, + net_stream_send_completed) == 0) { + net_stream_read_poll(s, false); + } +} + +static void net_stream_send(void *opaque) +{ + NetStreamState *s = opaque; + int size; + int ret; + uint8_t buf1[NET_BUFSIZE]; + const uint8_t *buf; + + size = recv(s->fd, buf1, sizeof(buf1), 0); + if (size < 0) { + if (errno != EWOULDBLOCK) { + goto eoc; + } + } else if (size == 0) { + /* end of connection */ + eoc: + net_stream_read_poll(s, false); + net_stream_write_poll(s, false); + if (s->listen_fd != -1) { + qemu_set_fd_handler(s->listen_fd, net_stream_accept, NULL, s); + } + closesocket(s->fd); + + s->fd = -1; + net_socket_rs_init(&s->rs, net_stream_rs_finalize, false); + s->nc.link_down = true; + qemu_set_info_str(&s->nc, ""); + + return; + } + buf = buf1; + + ret = net_fill_rstate(&s->rs, buf, size); + + if (ret == -1) { + goto eoc; + } +} + +static void net_stream_cleanup(NetClientState *nc) +{ + NetStreamState *s = DO_UPCAST(NetStreamState, nc, nc); + if (s->fd != -1) { + net_stream_read_poll(s, false); + net_stream_write_poll(s, false); + close(s->fd); + s->fd = -1; + } + if (s->listen_fd != -1) { + qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); + closesocket(s->listen_fd); + s->listen_fd = -1; + } +} + +static void net_stream_connect(void *opaque) +{ + NetStreamState *s = opaque; + net_stream_read_poll(s, true); +} + +static NetClientInfo net_stream_info = { + .type = NET_CLIENT_DRIVER_STREAM, + .size = sizeof(NetStreamState), + .receive = net_stream_receive, + .cleanup = net_stream_cleanup, +}; + +static NetStreamState *net_stream_fd_init(NetClientState *peer, + const char *model, + const char *name, + int fd, int is_connected) +{ + NetClientState *nc; + NetStreamState *s; + + nc = qemu_new_net_client(&net_stream_info, peer, model, name); + + qemu_set_info_str(nc, "fd=%d", fd); + + s = DO_UPCAST(NetStreamState, nc, nc); + + s->fd = fd; + s->listen_fd = -1; + net_socket_rs_init(&s->rs, net_stream_rs_finalize, false); + + /* Disable Nagle algorithm on TCP sockets to reduce latency */ + socket_set_nodelay(fd); + + if (is_connected) { + net_stream_connect(s); + } else { + qemu_set_fd_handler(s->fd, NULL, net_stream_connect, s); + } + return s; +} + +static void net_stream_accept(void *opaque) +{ + NetStreamState *s = opaque; + struct sockaddr_in saddr; + socklen_t len; + int fd; + + for (;;) { + len = sizeof(saddr); + fd = qemu_accept(s->listen_fd, (struct sockaddr *)&saddr, &len); + if (fd < 0 && errno != EINTR) { + return; + } else if (fd >= 0) { + qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); + break; + } + } + + s->fd = fd; + s->nc.link_down = false; + net_stream_connect(s); + qemu_set_info_str(&s->nc, "connection from %s:%d", + inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); +} + +static int net_stream_server_init(NetClientState *peer, + const char *model, + const char *name, + SocketAddress *addr, + Error **errp) +{ + NetClientState *nc; + NetStreamState *s; + int fd, ret; + + switch (addr->type) { + case SOCKET_ADDRESS_TYPE_INET: { + struct sockaddr_in saddr_in; + + if (convert_host_port(&saddr_in, addr->u.inet.host, addr->u.inet.port, + errp) < 0) { + return -1; + } + + fd = qemu_socket(PF_INET, SOCK_STREAM, 0); + if (fd < 0) { + error_setg_errno(errp, errno, "can't create stream socket"); + return -1; + } + qemu_socket_set_nonblock(fd); + + socket_set_fast_reuse(fd); + + ret = bind(fd, (struct sockaddr *)&saddr_in, sizeof(saddr_in)); + if (ret < 0) { + error_setg_errno(errp, errno, "can't bind ip=%s to socket", + inet_ntoa(saddr_in.sin_addr)); + closesocket(fd); + return -1; + } + break; + } + case SOCKET_ADDRESS_TYPE_FD: + fd = monitor_fd_param(monitor_cur(), addr->u.fd.str, errp); + if (fd == -1) { + return -1; + } + ret = qemu_socket_try_set_nonblock(fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + return -1; + } + break; + default: + error_setg(errp, "only support inet or fd type"); + return -1; + } + + ret = listen(fd, 0); + if (ret < 0) { + error_setg_errno(errp, errno, "can't listen on socket"); + closesocket(fd); + return -1; + } + + nc = qemu_new_net_client(&net_stream_info, peer, model, name); + s = DO_UPCAST(NetStreamState, nc, nc); + s->fd = -1; + s->listen_fd = fd; + s->nc.link_down = true; + net_socket_rs_init(&s->rs, net_stream_rs_finalize, false); + + qemu_set_fd_handler(s->listen_fd, net_stream_accept, NULL, s); + return 0; +} + +static int net_stream_client_init(NetClientState *peer, + const char *model, + const char *name, + SocketAddress *addr, + Error **errp) +{ + NetStreamState *s; + struct sockaddr_in saddr_in; + int fd, connected, ret; + + switch (addr->type) { + case SOCKET_ADDRESS_TYPE_INET: + if (convert_host_port(&saddr_in, addr->u.inet.host, addr->u.inet.port, + errp) < 0) { + return -1; + } + + fd = qemu_socket(PF_INET, SOCK_STREAM, 0); + if (fd < 0) { + error_setg_errno(errp, errno, "can't create stream socket"); + return -1; + } + qemu_socket_set_nonblock(fd); + + connected = 0; + for (;;) { + ret = connect(fd, (struct sockaddr *)&saddr_in, sizeof(saddr_in)); + if (ret < 0) { + if (errno == EINTR || errno == EWOULDBLOCK) { + /* continue */ + } else if (errno == EINPROGRESS || + errno == EALREADY || + errno == EINVAL) { + break; + } else { + error_setg_errno(errp, errno, "can't connect socket"); + closesocket(fd); + return -1; + } + } else { + connected = 1; + break; + } + } + break; + case SOCKET_ADDRESS_TYPE_FD: + fd = monitor_fd_param(monitor_cur(), addr->u.fd.str, errp); + if (fd == -1) { + return -1; + } + ret = qemu_socket_try_set_nonblock(fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + return -1; + } + connected = 1; + break; + default: + error_setg(errp, "only support inet or fd type"); + return -1; + } + + s = net_stream_fd_init(peer, model, name, fd, connected); + + switch (addr->type) { + case SOCKET_ADDRESS_TYPE_INET: + qemu_set_info_str(&s->nc, "connect to %s:%d", + inet_ntoa(saddr_in.sin_addr), + ntohs(saddr_in.sin_port)); + break; + case SOCKET_ADDRESS_TYPE_FD: + qemu_set_info_str(&s->nc, "connect to fd %d", fd); + break; + default: + g_assert_not_reached(); + } + + return 0; +} + +int net_init_stream(const Netdev *netdev, const char *name, + NetClientState *peer, Error **errp) +{ + const NetdevStreamOptions *sock; + + assert(netdev->type == NET_CLIENT_DRIVER_STREAM); + sock = &netdev->u.stream; + + if (!sock->has_server || sock->server) { + return net_stream_server_init(peer, "stream", name, sock->addr, errp); + } + return net_stream_client_init(peer, "stream", name, sock->addr, errp); +} diff --git a/qapi/net.json b/qapi/net.json index dd088c09c509..57bc7100cf02 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -7,6 +7,7 @@ ## { 'include': 'common.json' } +{ 'include': 'sockets.json' } ## # @set_link: @@ -573,6 +574,60 @@ '*isolated': 'bool' }, 'if': 'CONFIG_VMNET' } +## +# @NetdevStreamOptions: +# +# Configuration info for stream socket netdev +# +# @addr: socket address to listen on (server=true) +# or connect to (server=false) +# @server: create server socket (default: true) +# +# Only SocketAddress types 'inet' and 'fd' are supported. +# +# Since: 7.2 +## +{ 'struct': 'NetdevStreamOptions', + 'data': { + 'addr': 'SocketAddress', + '*server': 'bool' } } + +## +# @NetdevDgramOptions: +# +# Configuration info for datagram socket netdev. +# +# @remote: remote address +# @local: local address +# +# Only SocketAddress types 'inet' and 'fd' are supported. +# +# If remote address is present and it's a multicast address, local address +# is optional. Otherwise local address is required and remote address is +# optional. +# +# .. table:: Valid parameters combination table +# :widths: auto +# +# ============= ======== ===== +# remote local okay? +# ============= ======== ===== +# absent absent no +# absent not fd no +# absent fd yes +# multicast absent yes +# multicast present yes +# not multicast absent no +# not multicast present yes +# ============= ======== ===== +# +# Since: 7.2 +## +{ 'struct': 'NetdevDgramOptions', + 'data': { + '*local': 'SocketAddress', + '*remote': 'SocketAddress' } } + ## # @NetClientDriver: # @@ -584,10 +639,13 @@ # @vmnet-host since 7.1 # @vmnet-shared since 7.1 # @vmnet-bridged since 7.1 +# @stream since 7.2 +# @dgram since 7.2 ## { 'enum': 'NetClientDriver', - 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', - 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa', + 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'stream', + 'dgram', 'vde', 'bridge', 'hubport', 'netmap', 'vhost-user', + 'vhost-vdpa', { 'name': 'vmnet-host', 'if': 'CONFIG_VMNET' }, { 'name': 'vmnet-shared', 'if': 'CONFIG_VMNET' }, { 'name': 'vmnet-bridged', 'if': 'CONFIG_VMNET' }] } @@ -607,6 +665,8 @@ # 'vmnet-host' - since 7.1 # 'vmnet-shared' - since 7.1 # 'vmnet-bridged' - since 7.1 +# 'stream' since 7.2 +# 'dgram' since 7.2 ## { 'union': 'Netdev', 'base': { 'id': 'str', 'type': 'NetClientDriver' }, @@ -617,6 +677,8 @@ 'tap': 'NetdevTapOptions', 'l2tpv3': 'NetdevL2TPv3Options', 'socket': 'NetdevSocketOptions', + 'stream': 'NetdevStreamOptions', + 'dgram': 'NetdevDgramOptions', 'vde': 'NetdevVdeOptions', 'bridge': 'NetdevBridgeOptions', 'hubport': 'NetdevHubPortOptions', diff --git a/qemu-options.hx b/qemu-options.hx index 95b998a13b01..83c0f9fd0630 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2756,6 +2756,18 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, "-netdev socket,id=str[,fd=h][,udp=host:port][,localaddr=host:port]\n" " configure a network backend to connect to another network\n" " using an UDP tunnel\n" + "-netdev stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port\n" + "-netdev stream,id=str[,server=on|off],addr.type=fd,addr.str=file-descriptor\n" + " configure a network backend to connect to another network\n" + " using a socket connection in stream mode.\n" + "-netdev dgram,id=str,remote.type=inet,remote.host=maddr,remote.port=port[,local.type=inet,local.host=addr]\n" + "-netdev dgram,id=str,remote.type=inet,remote.host=maddr,remote.port=port[,local.type=fd,local.str=file-descriptor]\n" + " configure a network backend to connect to a multicast maddr and port\n" + " use ``local.host=addr`` to specify the host address to send packets from\n" + "-netdev dgram,id=str,local.type=inet,local.host=addr,local.port=port[,remote.type=inet,remote.host=addr,remote.port=port]\n" + "-netdev dgram,id=str,local.type=fd,local.str=file-descriptor\n" + " configure a network backend to connect to another network\n" + " using an UDP tunnel\n" #ifdef CONFIG_VDE "-netdev vde,id=str[,sock=socketpath][,port=n][,group=groupname][,mode=octalmode]\n" " configure a network backend to connect to port 'n' of a vde switch\n" From patchwork Tue Oct 11 20:05:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004322 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 79B6CC433F5 for ; Tue, 11 Oct 2022 20:32:08 +0000 (UTC) Received: from localhost ([::1]:47386 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLv5-0001zR-6K for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:32:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55052) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVy-0006PQ-FR for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:19 -0400 Received: from mout.kundenserver.de ([212.227.126.134]:35899) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVu-0003kl-Vt for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:09 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1Mzyi6-1p3bSX1O22-00x1UI; Tue, 11 Oct 2022 22:05:55 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org, Stefano Brivio Subject: [PATCH v11 07/17] net: socket: Don't ignore EINVAL on netdev socket connection Date: Tue, 11 Oct 2022 22:05:29 +0200 Message-Id: <20221011200539.1486809-8-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:s2d3Wu4MO8ol5DA6PF+FwRX2ngxklqX0Xg022HDVmevHfVNwSNH wNVip7KNnUp+1d6oD/lzE6UuU2ptIv0OUC+VJvfArwZSeHBalDq3QRxn9aursvew6XDrERc /dOp3LLGjARYN3oHDHZXdNFQvCtZZd07alTYAPeSy3wuoB56esM4Fv5u6IVhrkMxXYcxKpa 5jTmu3R9fuCPRsqmZtIZg== X-UI-Out-Filterresults: notjunk:1;V03:K0:SsKt/PrHzOg=:RxXaAGqCcFTPq1Ui9f+XFu QvGhxbqWiHZ93SyVG59hGfTFa1pHKN7gxx4s5r1HazWDiCTWTqZgh1JOM0QjIAR2qVAIawO74 F7UFf6X3vvQNZmy+cnbJMOfIW7FgvOG815DFO7IS5d8/1Jw9pEul+1jvw4SwyO7VYV1eNwjaz IDVf0LhI6rd8Y9lyKnHLrpSNIjooJYTeKyX8MhDgo5sR2BLGcNhqShiBbhB8mWeWw86NVVVhG rgKaUMU+P32b/fJ/xa0WqGa2ItdRfC9bpPhsmEhDwvFIeF7N5tNyNvWiK5YeDeAZ94KkLF5uK d6jkLKfETNs4Ist6FIMRTFs5Y1FliJ89R0cQ0/tagOcH998wYfIHWnM+z4YW9GTIxuJkUBR6F DWgGoHApOkSVQOwAb4p9vXeDhb/rdG8tgIy+3KhZYINESx5/0aL4miBAGAR6DyHYxG6vXqvqP e+Ah0OpluVNIb8ZLX6HrTZo4ITr9BnY5dbZpIOUWRXe36VIMxgX5lv8uDd3zvvsbHpZQe69Z/ txcFYbX4pBEYiu/19N+ZA5KddJlT+Qwp15ra9W5TJnZ2qyfgCWtjj2sjpdB87I6nOY9vr4hYw 2FBt0nOoWsD78F59XD6keFsE0sjo/b2xghk7A8K7wdkc2OI0BbIqmTVQQpykGTToyADJrGStn G997YVCvjhsCW/gyu7Fysj+2TXtFAuStHpH3Uadyaoqu8Ryc+aj5SHWMDlDn2ZDlSAXkGRBQj Yk2lf8kSWc7wJ+EJI5OuHXPeQXUqsZ1/ZXu+tmH0LtiU2SBZUUBQW6ac6rdFAW93/MfhicUoz fmWAe+T Received-SPF: permerror client-ip=212.227.126.134; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" From: Stefano Brivio Other errors are treated as failure by net_socket_connect_init(), but if connect() returns EINVAL, we'll fail silently. Remove the related exception. Signed-off-by: Stefano Brivio Signed-off-by: Laurent Vivier Reviewed-by: David Gibson Acked-by: Michael S. Tsirkin --- net/socket.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/socket.c b/net/socket.c index ade1ecf38b87..4944bb70d580 100644 --- a/net/socket.c +++ b/net/socket.c @@ -577,8 +577,7 @@ static int net_socket_connect_init(NetClientState *peer, if (errno == EINTR || errno == EWOULDBLOCK) { /* continue */ } else if (errno == EINPROGRESS || - errno == EALREADY || - errno == EINVAL) { + errno == EALREADY) { break; } else { error_setg_errno(errp, errno, "can't connect socket"); From patchwork Tue Oct 11 20:05:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004312 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 BC945C433FE for ; Tue, 11 Oct 2022 20:14:14 +0000 (UTC) Received: from localhost ([::1]:54792 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLdl-0006S6-5o for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:14:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55056) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVz-0006PS-10 for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:18 -0400 Received: from mout.kundenserver.de ([212.227.126.130]:52933) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVw-0003l6-6L for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:10 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MwfrG-1p6tmY3H2o-00y7x8; Tue, 11 Oct 2022 22:05:57 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org, Stefano Brivio Subject: [PATCH v11 08/17] net: stream: Don't ignore EINVAL on netdev socket connection Date: Tue, 11 Oct 2022 22:05:30 +0200 Message-Id: <20221011200539.1486809-9-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:hsXLS+idoNRuKDGwDRk5k6KJvjvwEodY2MyHrLAIA+6jzR3kbMo YyGSQ6QSZsQ0Y1Q60v7RcYI5u2aR0VecKnTza8nTft0FolUWPbc5ieffcOQE+Lba/08VqGO YoyNRcZjmjrLl/7WpLEbLKT2+KJgIAxW4eOJean9QgLqyv1mqbYYmEaqRBBRQyCbTKlr6jX oFqfndp3YTa2SJ0n2r2Vw== X-UI-Out-Filterresults: notjunk:1;V03:K0:44cApntTpF4=:uuFvEBLvztbGc76J9T6Y0x n4jZ/h2QXLOnV991KjsKN3na46udr4Xj6KC6iRba1cHIk3Y+z8mSzKlWRJ8v4Ybo+ptU6pH8Z qAV26xLr900crAaAB7p6HP1u3Ydp1fhoFKZoMLNRkCEmwVstb0PdeRmMs+62XXwkU3huzqZyQ PWl6pKYRyy8k8XYQlTxgzZXHeXJAoZrxqWaqh3h37km94Zm6L3v5+nzjItMrAfkqrN6sxOHyf +pIw65mqnXuz6+32+TceHcujYazPsdP9fZhlyaWl6D1tJS19/a1XzL0ShjTp6RCX5U4SqITKG pXoQPX5JcRM2ezxZa8vx/CQ5/g88eQr9uDRTTI2KifVokhCs71+4KoD9xigISSGPOkGM6P1dD IHGPpCP6E6bOh0Opss3fRv09QEqKweUSNEDzLPLQHq+kasqDLsaYQ2/bir2xAgoz8BOOm2kdd oIRjLAxTHc+OQHKC10exX7Du7J84Z2EfF6dOGjgQl0Wt8Rt3pLJ/2O0hwNY4ZOpeTjOYGNEQB c0SRaN+j7cxEIdP3XrrPsgl81e6d73LWmQw4poLO+MyPxtA8tk6/pfnbIhXFzrjS+QDPW6XR2 I3o6goKppnDWj6i7iRab5KbdZuAR+NFcD7bdJ/r3DtDHK3TnXC+BjOHl8xJ/GqueUTIIhgaWm BIyDBO0im1M6oNGiD9cPYjFCOdnenXb4oE+dLoUG6bqQDhIdoP6d8/mbUc0px1rUiRsd1p1uY 2uEOBuJSfgTdnlJlpSD/o89FXfBykvRVleieb3es8dLVZaF1A7LXrIdd8L+287FFc0Rjt1/fc qooeXv7 Received-SPF: permerror client-ip=212.227.126.130; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" From: Stefano Brivio Other errors are treated as failure by net_stream_client_init(), but if connect() returns EINVAL, we'll fail silently. Remove the related exception. Signed-off-by: Stefano Brivio [lvivier: applied to net/stream.c] Signed-off-by: Laurent Vivier Reviewed-by: Daniel P. Berrangé Reviewed-by: David Gibson Acked-by: Michael S. Tsirkin --- net/stream.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/stream.c b/net/stream.c index 37965eb74e1a..26e485438718 100644 --- a/net/stream.c +++ b/net/stream.c @@ -360,8 +360,7 @@ static int net_stream_client_init(NetClientState *peer, if (errno == EINTR || errno == EWOULDBLOCK) { /* continue */ } else if (errno == EINPROGRESS || - errno == EALREADY || - errno == EINVAL) { + errno == EALREADY) { break; } else { error_setg_errno(errp, errno, "can't connect socket"); From patchwork Tue Oct 11 20:05:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004317 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 E98DAC433FE for ; Tue, 11 Oct 2022 20:24:51 +0000 (UTC) Received: from localhost ([::1]:51708 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLo2-00048B-Sc for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:24:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55058) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLW0-0006Pa-IA for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:19 -0400 Received: from mout.kundenserver.de ([212.227.126.131]:52275) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVy-0003lI-Bz for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:12 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MIdNt-1ouDbf14LN-00EeHJ; Tue, 11 Oct 2022 22:05:58 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org, Stefano Brivio Subject: [PATCH v11 09/17] net: stream: add unix socket Date: Tue, 11 Oct 2022 22:05:31 +0200 Message-Id: <20221011200539.1486809-10-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:TTHfVWOgPgee4bZdwhYPecNKVWtAvUXEFq4LgYltpAsxHaGFLZi Bbowmq/q7DgrZKJcL+oo3DMFMYNV3KX94C8xyf4MnsLqa3HoHCU2Wr7gK4fQrBT6FEW0gh4 8MnHiRvJq4mlhw7r3YCAufenYjX5SmDTzCmOdeDHq1itgsak3KXVhBi02CM6sr/xQpcxOlj 0WdOA+4tT7jaczBDOC8uA== X-UI-Out-Filterresults: notjunk:1;V03:K0:i5UNhCj3wgA=:EcVvztxxjJbSBfe65Ew/L7 CapUFLFRHeHKowk51tPqzPHSo1XNxsCtSeNFfq5A/d6tYh+XckRTK29jE6QNM24YlLBEnyDFl fQAfyUS/BpctF7vPF6TdxMC7jDc5sTCuqF41uxCkQMqd6ybbdJQhcnD2KOFDDOyJqdeqwf951 NS7ARG814ST/57/q1D/Od6/ueBIHYjcCPcFuuYdxlFi+GzKL9648bbIZnyGZJcsihGJbLedSF fR2YiS5FYEjZn8Fx04wSwbyKScXNSxRpqxTHiXBeQusSWwGbdvWX+sbTZLVk4Cc3qSAMGEoap O0F3xdv1bFbreqLzZv5gqsXC0vPD0rONVytJkREkI6G0DLqw0Yn3Fx8WXONZgQIHkU8jbEcua DPcdFkMzcFJm4Utjl70aa7oc5sbPbO2vBcrKJ8XRHeSXmn6AyN+fIR1G87QviemBs34ub8Qsi E1cOsMmiFVZqtp7awg6fnSWe0GMFr76ioi5HuDZgVc7WWoVyqBsCuH34t0Wf0pe3DstIk3aPm ACh/uqUACrqEtpyufCiiBVjvoM7BuITZm9aps1IaSS+l+Z6QxXCaZESqqaRkDxUTpB6znJA48 hLiPPF4lNycouxEsvCGvffBay0K68ZH8YMFZJGX2vt9sRX9XN/uNo6MFuIu/VLeiaFThhqom8 1OpX8Hbx8Krz1QOChguMtbMLQr/wcyaZzBYjMvG621SHKxtXlgNMsA/3GV8jyl47h5UJZDBj1 5/qIQ1vDJpO2Nb5cKb5hv7m1YxdIu2ww4JACYOk4CceXbTNFXC8rcUwKOVnKeOMGzw+Otit1N GNRiyGD Received-SPF: permerror client-ip=212.227.126.131; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" Signed-off-by: Laurent Vivier Reviewed-by: Stefano Brivio Acked-by: Michael S. Tsirkin Acked-by: Markus Armbruster --- net/stream.c | 107 +++++++++++++++++++++++++++++++++++++++++++++--- qapi/net.json | 2 +- qemu-options.hx | 1 + 3 files changed, 104 insertions(+), 6 deletions(-) diff --git a/net/stream.c b/net/stream.c index 26e485438718..d26c79d035fc 100644 --- a/net/stream.c +++ b/net/stream.c @@ -235,7 +235,7 @@ static NetStreamState *net_stream_fd_init(NetClientState *peer, static void net_stream_accept(void *opaque) { NetStreamState *s = opaque; - struct sockaddr_in saddr; + struct sockaddr_storage saddr; socklen_t len; int fd; @@ -253,8 +253,26 @@ static void net_stream_accept(void *opaque) s->fd = fd; s->nc.link_down = false; net_stream_connect(s); - qemu_set_info_str(&s->nc, "connection from %s:%d", - inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); + switch (saddr.ss_family) { + case AF_INET: { + struct sockaddr_in *saddr_in = (struct sockaddr_in *)&saddr; + + qemu_set_info_str(&s->nc, "connection from %s:%d", + inet_ntoa(saddr_in->sin_addr), + ntohs(saddr_in->sin_port)); + break; + } + case AF_UNIX: { + struct sockaddr_un saddr_un; + + len = sizeof(saddr_un); + getsockname(s->listen_fd, (struct sockaddr *)&saddr_un, &len); + qemu_set_info_str(&s->nc, "connect from %s", saddr_un.sun_path); + break; + } + default: + g_assert_not_reached(); + } } static int net_stream_server_init(NetClientState *peer, @@ -294,6 +312,43 @@ static int net_stream_server_init(NetClientState *peer, } break; } + case SOCKET_ADDRESS_TYPE_UNIX: { + struct sockaddr_un saddr_un; + + ret = unlink(addr->u.q_unix.path); + if (ret < 0 && errno != ENOENT) { + error_setg_errno(errp, errno, "failed to unlink socket %s", + addr->u.q_unix.path); + return -1; + } + + saddr_un.sun_family = PF_UNIX; + ret = snprintf(saddr_un.sun_path, sizeof(saddr_un.sun_path), "%s", + addr->u.q_unix.path); + if (ret < 0 || ret >= sizeof(saddr_un.sun_path)) { + error_setg(errp, "UNIX socket path '%s' is too long", + addr->u.q_unix.path); + error_append_hint(errp, "Path must be less than %zu bytes\n", + sizeof(saddr_un.sun_path)); + return -1; + } + + fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + error_setg_errno(errp, errno, "can't create stream socket"); + return -1; + } + qemu_socket_set_nonblock(fd); + + ret = bind(fd, (struct sockaddr *)&saddr_un, sizeof(saddr_un)); + if (ret < 0) { + error_setg_errno(errp, errno, "can't create socket with path: %s", + saddr_un.sun_path); + closesocket(fd); + return -1; + } + break; + } case SOCKET_ADDRESS_TYPE_FD: fd = monitor_fd_param(monitor_cur(), addr->u.fd.str, errp); if (fd == -1) { @@ -337,6 +392,7 @@ static int net_stream_client_init(NetClientState *peer, { NetStreamState *s; struct sockaddr_in saddr_in; + struct sockaddr_un saddr_un; int fd, connected, ret; switch (addr->type) { @@ -373,6 +429,45 @@ static int net_stream_client_init(NetClientState *peer, } } break; + case SOCKET_ADDRESS_TYPE_UNIX: + saddr_un.sun_family = PF_UNIX; + ret = snprintf(saddr_un.sun_path, sizeof(saddr_un.sun_path), "%s", + addr->u.q_unix.path); + if (ret < 0 || ret >= sizeof(saddr_un.sun_path)) { + error_setg(errp, "UNIX socket path '%s' is too long", + addr->u.q_unix.path); + error_append_hint(errp, "Path must be less than %zu bytes\n", + sizeof(saddr_un.sun_path)); + return -1; + } + + fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + error_setg_errno(errp, errno, "can't create stream socket"); + return -1; + } + qemu_socket_set_nonblock(fd); + + connected = 0; + for (;;) { + ret = connect(fd, (struct sockaddr *)&saddr_un, sizeof(saddr_un)); + if (ret < 0) { + if (errno == EINTR || errno == EWOULDBLOCK) { + /* continue */ + } else if (errno == EAGAIN || + errno == EALREADY) { + break; + } else { + error_setg_errno(errp, errno, "can't connect socket"); + closesocket(fd); + return -1; + } + } else { + connected = 1; + break; + } + } + break; case SOCKET_ADDRESS_TYPE_FD: fd = monitor_fd_param(monitor_cur(), addr->u.fd.str, errp); if (fd == -1) { @@ -387,7 +482,7 @@ static int net_stream_client_init(NetClientState *peer, connected = 1; break; default: - error_setg(errp, "only support inet or fd type"); + error_setg(errp, "only support inet, unix or fd type"); return -1; } @@ -399,13 +494,15 @@ static int net_stream_client_init(NetClientState *peer, inet_ntoa(saddr_in.sin_addr), ntohs(saddr_in.sin_port)); break; + case SOCKET_ADDRESS_TYPE_UNIX: + qemu_set_info_str(&s->nc, " connect to %s", saddr_un.sun_path); + break; case SOCKET_ADDRESS_TYPE_FD: qemu_set_info_str(&s->nc, "connect to fd %d", fd); break; default: g_assert_not_reached(); } - return 0; } diff --git a/qapi/net.json b/qapi/net.json index 57bc7100cf02..a85eddcaed92 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -583,7 +583,7 @@ # or connect to (server=false) # @server: create server socket (default: true) # -# Only SocketAddress types 'inet' and 'fd' are supported. +# Only SocketAddress types 'unix', 'inet' and 'fd' are supported. # # Since: 7.2 ## diff --git a/qemu-options.hx b/qemu-options.hx index 83c0f9fd0630..242c45e44af3 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2757,6 +2757,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, " configure a network backend to connect to another network\n" " using an UDP tunnel\n" "-netdev stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port\n" + "-netdev stream,id=str[,server=on|off],addr.type=unix,addr.path=path\n" "-netdev stream,id=str[,server=on|off],addr.type=fd,addr.str=file-descriptor\n" " configure a network backend to connect to another network\n" " using a socket connection in stream mode.\n" From patchwork Tue Oct 11 20:05:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004323 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 3962DC433FE for ; Tue, 11 Oct 2022 20:36:46 +0000 (UTC) Received: from localhost ([::1]:39876 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLzZ-0007IV-4S for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:36:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55060) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLW0-0006Pb-Iv for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:20 -0400 Received: from mout.kundenserver.de ([212.227.126.133]:36079) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLVy-0003lE-72 for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:12 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N2Ujn-1p9wAi30CV-013t7r; Tue, 11 Oct 2022 22:06:00 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org, Stefano Brivio Subject: [PATCH v11 10/17] net: dgram: make dgram_dst generic Date: Tue, 11 Oct 2022 22:05:32 +0200 Message-Id: <20221011200539.1486809-11-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:mej7cnifO8Mk5n6kRHCS/Ch3oXeRsA1xv31dK1e5Man9+8wiSPh FZ9ulsjdhM0i6b/olyMprHqPfhAqyspaUMNEMOk4cMPrSQFY/z/MTKtvQd7cNsRrMLbApbg J1amHxjIaEle/AtNYaB4Dtv9V9wFcvIeu7+Gn/or3BaRcRr1GiBzqZ9sYKwKJF/05eCxhDG 6I0clpj62qPYAK5hYjYaA== X-UI-Out-Filterresults: notjunk:1;V03:K0:J0TF2aWliOo=:BPXg9n1pCmKLD6cojC6G1+ p2pruc297vkkHWWMsS6XFm+AOtdbcnOEt0BKJ7yqr16GF250tQQeT0ThVqfeASv7oJcb4lQJ5 vXf1Z2URE5K1J683wbRgj+U1OADWen+z6kJtOskaJse1dwO9axbouIreXSv51tJSzrRT2y6eF 5pJeS9Hp42FlQYU6ltICXpg27pDYB95MCSEGNujJ9sjPrM7EYYc/M6b+BsYtGiNBgdKL5DuxV BZmuDjM9XHd4Dno5QYS2qYS0d9oDr2UIWsxEF9ziBS4zeEIrjk06j4FbaMqHa6VMfT6PJMWWi 3II2dcwc6ypnaOrEyT2d1Putr+jnwGfZQLt7Rh/EEeJWcoKlnzzRYIfwkfY/uByhOYtN6LCsT r21NhCDKanT2V453DodX9Rl4p2kYyG2+g8WTyBGQOsjCs6qfyBfZbFDlFNLDP1Iwri/KzEUJ3 qV9fW5LzZMH1bXnYTjLFRm9E9SubUClh+sZnsxeMDaTPhjxudHOAADiAS/IhlHFg4L51mKh+I uoYYu3OnWxSNkzCy5aVn9b9GnGNgU+lZ/ww2CcDIeRFhKxtojBg/yugUgcL8JSkZqoSREsM3p oicx9NWC30jHzob9YGzkThVx9o2q3lq8Lr/JyQV7rG5ZERgM+yZvTu0yPx7dQJBkZTpAxrJE0 LwnsfzYNhSM6XW//UI4IWx9pPzjzVdKhS5tNuqO1b+uljJwAKoNsqxumfjJuHgsK3iyQquyZ3 6dhJhg/Ljkmg5IkHRqvi2iGJ/biFuK7aGB50VzL7ha/o0t+pOPWDbHDBT7G3eIVbVdGJjQYYZ T1dtztp Received-SPF: permerror client-ip=212.227.126.133; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" dgram_dst is a sockaddr_in structure. To be able to use it with unix socket, use a pointer to a generic sockaddr structure. Rename it dest_addr, and store socket length in dest_len. Signed-off-by: Laurent Vivier Reviewed-by: Stefano Brivio Acked-by: Michael S. Tsirkin --- net/dgram.c | 82 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/net/dgram.c b/net/dgram.c index 5339585b8202..e20be9ca79d3 100644 --- a/net/dgram.c +++ b/net/dgram.c @@ -40,9 +40,11 @@ typedef struct NetDgramState { NetClientState nc; int fd; SocketReadState rs; - struct sockaddr_in dgram_dst; /* contains destination iff connectionless */ bool read_poll; /* waiting to receive data? */ bool write_poll; /* waiting to transmit data? */ + /* contains destination iff connectionless */ + struct sockaddr *dest_addr; + socklen_t dest_len; } NetDgramState; static void net_dgram_send(void *opaque); @@ -84,10 +86,8 @@ static ssize_t net_dgram_receive(NetClientState *nc, ssize_t ret; do { - if (s->dgram_dst.sin_family != AF_UNIX) { - ret = sendto(s->fd, buf, size, 0, - (struct sockaddr *)&s->dgram_dst, - sizeof(s->dgram_dst)); + if (s->dest_addr) { + ret = sendto(s->fd, buf, size, 0, s->dest_addr, s->dest_len); } else { ret = send(s->fd, buf, size, 0); } @@ -244,6 +244,9 @@ static void net_dgram_cleanup(NetClientState *nc) close(s->fd); s->fd = -1; } + g_free(s->dest_addr); + s->dest_addr = NULL; + s->dest_len = 0; } static NetClientInfo net_dgram_socket_info = { @@ -260,7 +263,7 @@ static NetDgramState *net_dgram_fd_init(NetClientState *peer, SocketAddress *mcast, Error **errp) { - struct sockaddr_in saddr; + struct sockaddr_in *saddr = NULL; int newfd; NetClientState *nc; NetDgramState *s; @@ -275,31 +278,32 @@ static NetDgramState *net_dgram_fd_init(NetClientState *peer, qapi_free_SocketAddress(sa); /* - * fd passed: multicast: "learn" dgram_dst address from bound address and + * fd passed: multicast: "learn" dest_addr address from bound address and * save it. Because this may be "shared" socket from a "master" process, * datagrams would be recv() by ONLY ONE process: we must "clone" this * dgram socket --jjo */ if (is_fd && mcast != NULL) { - if (convert_host_port(&saddr, mcast->u.inet.host, - mcast->u.inet.port, errp) < 0) { + saddr = g_new(struct sockaddr_in, 1); + + if (convert_host_port(saddr, mcast->u.inet.host, mcast->u.inet.port, + errp) < 0) { goto err; } /* must be bound */ - if (saddr.sin_addr.s_addr == 0) { + if (saddr->sin_addr.s_addr == 0) { error_setg(errp, "can't setup multicast destination address"); goto err; } /* clone dgram socket */ - newfd = net_dgram_mcast_create(&saddr, NULL, errp); + newfd = net_dgram_mcast_create(saddr, NULL, errp); if (newfd < 0) { goto err; } /* clone newfd to fd, close newfd */ dup2(newfd, fd); close(newfd); - } nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name); @@ -311,21 +315,20 @@ static NetDgramState *net_dgram_fd_init(NetClientState *peer, net_dgram_read_poll(s, true); /* mcast: save bound address as dst */ - if (is_fd && mcast != NULL) { - s->dgram_dst = saddr; + if (saddr) { + g_assert(s->dest_addr == NULL); + s->dest_addr = (struct sockaddr *)saddr; + s->dest_len = sizeof(*saddr); qemu_set_info_str(nc, "fd=%d (cloned mcast=%s:%d)", fd, - inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); + inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port)); } else { - if (sa_type == SOCKET_ADDRESS_TYPE_UNIX) { - s->dgram_dst.sin_family = AF_UNIX; - } - qemu_set_info_str(nc, "fd=%d %s", fd, SocketAddressType_str(sa_type)); } return s; err: + g_free(saddr); closesocket(fd); return NULL; } @@ -339,21 +342,24 @@ static int net_dgram_mcast_init(NetClientState *peer, { NetDgramState *s; int fd, ret; - struct sockaddr_in saddr; + struct sockaddr_in *saddr; if (remote->type != SOCKET_ADDRESS_TYPE_INET) { error_setg(errp, "multicast only support inet type"); return -1; } - if (convert_host_port(&saddr, remote->u.inet.host, remote->u.inet.port, + saddr = g_new(struct sockaddr_in, 1); + if (convert_host_port(saddr, remote->u.inet.host, remote->u.inet.port, errp) < 0) { + g_free(saddr); return -1; } if (!local) { - fd = net_dgram_mcast_create(&saddr, NULL, errp); + fd = net_dgram_mcast_create(saddr, NULL, errp); if (fd < 0) { + g_free(saddr); return -1; } } else { @@ -362,13 +368,15 @@ static int net_dgram_mcast_init(NetClientState *peer, struct in_addr localaddr; if (inet_aton(local->u.inet.host, &localaddr) == 0) { + g_free(saddr); error_setg(errp, "localaddr '%s' is not a valid IPv4 address", local->u.inet.host); return -1; } - fd = net_dgram_mcast_create(&saddr, &localaddr, errp); + fd = net_dgram_mcast_create(saddr, &localaddr, errp); if (fd < 0) { + g_free(saddr); return -1; } break; @@ -376,16 +384,19 @@ static int net_dgram_mcast_init(NetClientState *peer, case SOCKET_ADDRESS_TYPE_FD: fd = monitor_fd_param(monitor_cur(), local->u.fd.str, errp); if (fd == -1) { + g_free(saddr); return -1; } ret = qemu_socket_try_set_nonblock(fd); if (ret < 0) { + g_free(saddr); error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", name, fd); return -1; } break; default: + g_free(saddr); error_setg(errp, "only support inet or fd type for local"); return -1; } @@ -395,13 +406,17 @@ static int net_dgram_mcast_init(NetClientState *peer, local->type == SOCKET_ADDRESS_TYPE_FD, remote, errp); if (!s) { + g_free(saddr); return -1; } - s->dgram_dst = saddr; + g_assert(s->dest_addr == NULL); + s->dest_addr = (struct sockaddr *)saddr; + s->dest_len = sizeof(*saddr); + + qemu_set_info_str(&s->nc, "mcast=%s:%d", inet_ntoa(saddr->sin_addr), + ntohs(saddr->sin_port)); - qemu_set_info_str(&s->nc, "mcast=%s:%d", inet_ntoa(saddr.sin_addr), - ntohs(saddr.sin_port)); return 0; } @@ -412,9 +427,10 @@ int net_init_dgram(const Netdev *netdev, const char *name, { NetDgramState *s; int fd, ret; - struct sockaddr_in raddr_in; - struct sockaddr_in laddr_in; SocketAddress *remote, *local; + struct sockaddr *dest_addr; + struct sockaddr_in laddr_in, raddr_in; + socklen_t dest_len; assert(netdev->type == NET_CLIENT_DRIVER_DGRAM); @@ -491,6 +507,10 @@ int net_init_dgram(const Netdev *netdev, const char *name, return -1; } qemu_socket_set_nonblock(fd); + + dest_len = sizeof(raddr_in); + dest_addr = g_malloc(dest_len); + memcpy(dest_addr, &raddr_in, dest_len); break; case SOCKET_ADDRESS_TYPE_FD: fd = monitor_fd_param(monitor_cur(), local->u.fd.str, errp); @@ -503,6 +523,8 @@ int net_init_dgram(const Netdev *netdev, const char *name, name, fd); return -1; } + dest_addr = NULL; + dest_len = 0; break; default: error_setg(errp, "only support inet or fd type for local"); @@ -515,7 +537,9 @@ int net_init_dgram(const Netdev *netdev, const char *name, } if (remote) { - s->dgram_dst = raddr_in; + g_assert(s->dest_addr == NULL); + s->dest_addr = dest_addr; + s->dest_len = dest_len; } switch (local->type) { From patchwork Tue Oct 11 20:05:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004320 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 EC371C433F5 for ; Tue, 11 Oct 2022 20:31:33 +0000 (UTC) Received: from localhost ([::1]:50606 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLuW-0001Lh-KO for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:31:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55064) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLW3-0006Pk-D8 for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:20 -0400 Received: from mout.kundenserver.de ([212.227.126.134]:51373) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLW1-0003ll-BX for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:15 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MWixU-1og7X70yQy-00X0c0; Tue, 11 Oct 2022 22:06:01 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org, Stefano Brivio Subject: [PATCH v11 11/17] net: dgram: move mcast specific code from net_socket_fd_init_dgram() Date: Tue, 11 Oct 2022 22:05:33 +0200 Message-Id: <20221011200539.1486809-12-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:F1WBOjes54Ktx9ZJasV0Hab4sIMUR/z2M3jvkx2EPwUQPltAOCa y1XLW8Oj6A59NXmTOzuu/5XLhRXcTdHx/2y4rx0F8dMCoLfq6sRFmVbYQdrkWeb5A1w+ReD dZfkGUutwbsz/4BqwdDSTgUJpnXng+v+LVPyuro0xgJbBDwOfjL90X4hyn2261T2rM/PYCn FuM+zRiXY9IzbNPLArrBQ== X-UI-Out-Filterresults: notjunk:1;V03:K0:Js7oq39HmRI=:mRAqevwrzuxkvuEpNSBN3W 6E+w49WgogP7r3Tfx15xZkL9cTdmamflmPGaaIPxKS/rTv2irM0GTlpDe16DBjPfcrP/XiYgM obCKvNxaXUS428WK7A/qFIc09c3sCzMhmASM0nLJz1G4z2oYHcftzE3/MGRMVGgAUB22J6UrJ qPvNfDSS/7jYGjYiUk/X+3cO5g2cH978c1UdzOGRJ+orqJP76DzbpulF0ZG78EKncb4WUlKyt J9DZ5jFgEfnNTmBp/tz1fumKi+tZzPGIO2PcIG7Ra8+eI88pPY0qecHEqULhWybInyaDIbcVB 1K3YpzRyxCrbLlF9G3j59r9WP16c5+VdpKM8GfbjuCUfs1BU8+VQAZzEtmMRpeYUmlGoCyWCa 7qQoVHp51ONpaU3FKgY3Hz3MUgcXmqirBe19MHaWsR3eBBqJLB3Cj0a9yHxvKe4yDjrghcw2j 00yjqV0rnwGCnjH3AOnXIqeN4HoglOw3iavd8l8TyZfzu8NUK4BMxpHCLlPNTkprwCXIbYfEJ FkfMlCrjKnigGoECX4WBtQNayuBn+BE07NHVtz/HzVkvSQrT8ZwpccoyBVLcdr8jS8XgxPKlP uJy3Xzg13FTrPVd0kYc1ZYidA47IB11HKF8PSn7zo7MIb6LzR180h5ZAMk02simUNPHy0pw1Q 26mvqnpPuD1XsoyOF0gGD8snVxbfub6R8L15TZQ8T86/i1QdY/6y2GvwwdKLeN3dA0c5ODMs8 WPhfvG5T9a3VHvW0jngim+BebPJYi25ugxVx/PCuWBdZLs75hjeqdVndVo7oOLzeXMFqdVkYz 25LRVFM Received-SPF: permerror client-ip=212.227.126.134; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" It is less complex to manage special cases directly in net_dgram_mcast_init() and net_dgram_udp_init(). Signed-off-by: Laurent Vivier Reviewed-by: Stefano Brivio Acked-by: Michael S. Tsirkin --- net/dgram.c | 143 ++++++++++++++++++++++++++++------------------------ 1 file changed, 76 insertions(+), 67 deletions(-) diff --git a/net/dgram.c b/net/dgram.c index e20be9ca79d3..e581cc62f39f 100644 --- a/net/dgram.c +++ b/net/dgram.c @@ -259,52 +259,11 @@ static NetClientInfo net_dgram_socket_info = { static NetDgramState *net_dgram_fd_init(NetClientState *peer, const char *model, const char *name, - int fd, int is_fd, - SocketAddress *mcast, + int fd, Error **errp) { - struct sockaddr_in *saddr = NULL; - int newfd; NetClientState *nc; NetDgramState *s; - SocketAddress *sa; - SocketAddressType sa_type; - - sa = socket_local_address(fd, errp); - if (!sa) { - return NULL; - } - sa_type = sa->type; - qapi_free_SocketAddress(sa); - - /* - * fd passed: multicast: "learn" dest_addr address from bound address and - * save it. Because this may be "shared" socket from a "master" process, - * datagrams would be recv() by ONLY ONE process: we must "clone" this - * dgram socket --jjo - */ - - if (is_fd && mcast != NULL) { - saddr = g_new(struct sockaddr_in, 1); - - if (convert_host_port(saddr, mcast->u.inet.host, mcast->u.inet.port, - errp) < 0) { - goto err; - } - /* must be bound */ - if (saddr->sin_addr.s_addr == 0) { - error_setg(errp, "can't setup multicast destination address"); - goto err; - } - /* clone dgram socket */ - newfd = net_dgram_mcast_create(saddr, NULL, errp); - if (newfd < 0) { - goto err; - } - /* clone newfd to fd, close newfd */ - dup2(newfd, fd); - close(newfd); - } nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name); @@ -314,23 +273,7 @@ static NetDgramState *net_dgram_fd_init(NetClientState *peer, net_socket_rs_init(&s->rs, net_dgram_rs_finalize, false); net_dgram_read_poll(s, true); - /* mcast: save bound address as dst */ - if (saddr) { - g_assert(s->dest_addr == NULL); - s->dest_addr = (struct sockaddr *)saddr; - s->dest_len = sizeof(*saddr); - qemu_set_info_str(nc, "fd=%d (cloned mcast=%s:%d)", fd, - inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port)); - } else { - qemu_set_info_str(nc, "fd=%d %s", fd, SocketAddressType_str(sa_type)); - } - return s; - -err: - g_free(saddr); - closesocket(fd); - return NULL; } static int net_dgram_mcast_init(NetClientState *peer, @@ -381,7 +324,9 @@ static int net_dgram_mcast_init(NetClientState *peer, } break; } - case SOCKET_ADDRESS_TYPE_FD: + case SOCKET_ADDRESS_TYPE_FD: { + int newfd; + fd = monitor_fd_param(monitor_cur(), local->u.fd.str, errp); if (fd == -1) { g_free(saddr); @@ -394,7 +339,42 @@ static int net_dgram_mcast_init(NetClientState *peer, name, fd); return -1; } + + /* + * fd passed: multicast: "learn" dest_addr address from bound + * address and save it. Because this may be "shared" socket from a + * "master" process, datagrams would be recv() by ONLY ONE process: + * we must "clone" this dgram socket --jjo + */ + + saddr = g_new(struct sockaddr_in, 1); + + if (convert_host_port(saddr, local->u.inet.host, local->u.inet.port, + errp) < 0) { + g_free(saddr); + closesocket(fd); + return -1; + } + + /* must be bound */ + if (saddr->sin_addr.s_addr == 0) { + error_setg(errp, "can't setup multicast destination address"); + g_free(saddr); + closesocket(fd); + return -1; + } + /* clone dgram socket */ + newfd = net_dgram_mcast_create(saddr, NULL, errp); + if (newfd < 0) { + g_free(saddr); + closesocket(fd); + return -1; + } + /* clone newfd to fd, close newfd */ + dup2(newfd, fd); + close(newfd); break; + } default: g_free(saddr); error_setg(errp, "only support inet or fd type for local"); @@ -402,9 +382,7 @@ static int net_dgram_mcast_init(NetClientState *peer, } } - s = net_dgram_fd_init(peer, model, name, fd, - local->type == SOCKET_ADDRESS_TYPE_FD, - remote, errp); + s = net_dgram_fd_init(peer, model, name, fd, errp); if (!s) { g_free(saddr); return -1; @@ -414,8 +392,26 @@ static int net_dgram_mcast_init(NetClientState *peer, s->dest_addr = (struct sockaddr *)saddr; s->dest_len = sizeof(*saddr); - qemu_set_info_str(&s->nc, "mcast=%s:%d", inet_ntoa(saddr->sin_addr), - ntohs(saddr->sin_port)); + if (!local) { + qemu_set_info_str(&s->nc, "mcast=%s:%d", + inet_ntoa(saddr->sin_addr), + ntohs(saddr->sin_port)); + } else { + switch (local->type) { + case SOCKET_ADDRESS_TYPE_INET: + qemu_set_info_str(&s->nc, "mcast=%s:%d", + inet_ntoa(saddr->sin_addr), + ntohs(saddr->sin_port)); + break; + case SOCKET_ADDRESS_TYPE_FD: + qemu_set_info_str(&s->nc, "fd=%d (cloned mcast=%s:%d)", + fd, inet_ntoa(saddr->sin_addr), + ntohs(saddr->sin_port)); + break; + default: + g_assert_not_reached(); + } + } return 0; @@ -531,7 +527,7 @@ int net_init_dgram(const Netdev *netdev, const char *name, return -1; } - s = net_dgram_fd_init(peer, "dgram", name, fd, 0, NULL, errp); + s = net_dgram_fd_init(peer, "dgram", name, fd, errp); if (!s) { return -1; } @@ -550,9 +546,22 @@ int net_init_dgram(const Netdev *netdev, const char *name, inet_ntoa(raddr_in.sin_addr), ntohs(raddr_in.sin_port)); break; - case SOCKET_ADDRESS_TYPE_FD: - qemu_set_info_str(&s->nc, "fd=%d", fd); + case SOCKET_ADDRESS_TYPE_FD: { + SocketAddress *sa; + SocketAddressType sa_type; + + sa = socket_local_address(fd, errp); + if (sa) { + sa_type = sa->type; + qapi_free_SocketAddress(sa); + + qemu_set_info_str(&s->nc, "fd=%d %s", fd, + SocketAddressType_str(sa_type)); + } else { + qemu_set_info_str(&s->nc, "fd=%d", fd); + } break; + } default: g_assert_not_reached(); } From patchwork Tue Oct 11 20:05:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004321 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 9249EC433F5 for ; Tue, 11 Oct 2022 20:31:39 +0000 (UTC) Received: from localhost ([::1]:57710 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLuc-0001bB-Kw for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:31:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60968) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLWQ-0006TI-JE for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:39 -0400 Received: from mout.kundenserver.de ([212.227.126.130]:34879) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLWM-0003mV-VD for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:38 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MhDN4-1pMNIW36u2-00eOAw; Tue, 11 Oct 2022 22:06:02 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org, Stefano Brivio Subject: [PATCH v11 12/17] net: dgram: add unix socket Date: Tue, 11 Oct 2022 22:05:34 +0200 Message-Id: <20221011200539.1486809-13-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:XuRv6YlPVi6FRA/fjhO84WriOjNT0FImrBOgKhXbtqSEe+PMIs0 EaW5SC7InPXCMhQuVEvgjSgXldbptMOsFBsFMg+zad7WIwgPi4RLy01/m9rvc6+09n1TC/n 4RQlRCB/BKCDtOgJBP94I4hTpxAWajpqFwgrtS2OeqD8Y0eafWTUcAYgwG8WbeIoat3RJ20 GWEfUuS1CdqXhu9pn/TbQ== X-UI-Out-Filterresults: notjunk:1;V03:K0:F+UoKJRLAf0=:R1OgNZ9BAKbH4YMWAHZQwD ieQYCJCZCfI9ZWDIPQo5U/8mPYrNELwjTcSEND9CfOrJ5jrt5dbn+RiYd0fKor8SNe6DwtbOP xCJyVgpMwd1EIfoAkrOGP4E29Mgt6Qnh7bSiYMJ7rz56jNwi1LLCCPMm7csC/CR2lX0qQlFuf fQC5L5xuH+ieapfshoK1rjIF+efF6EcZS7Ft6S6QRHBdowV6+hgnGaeXojEVmSWsu52glWEuV OhRDCjucMEUPFIhokPeeVniwvi78icrBLQa76zg17LO/uTNfN3ojM4ziPT8VxoBqaUPf+4R4B xAzotI2WfvHTnxCr860PAF3w93M2Z8oKah2ZGf5tpSSoDTYea+8rGFKrEV3I9VBMizcTMK8Uh RRZ4/hZcllofnVom4os/aBfiRxDENTKuntdRuOzXb1u2rlSDtFBC5KvhAKQRoElHyKhpn8mNL Z0I8kIniGDohTCgKiN/LdC0u9ce74u9gNzhOGjMJ/UDOEghPRCwdJZmBR/ce/cXrrv2uwLi0U HbcCWsxDXhyK8zQoJLKoXRNPJvR23QVRfTpYSCp/ae16AJ6taEcca+7yMniiJRb9lv6fihrBV hI6p3NzeVzdXF+K6Apaz7R8u8gkN0bJjN5pyxCoeVVxMruMwH7iEr8IVEdqAlS7K5koVNn+sQ sGiwtB+tSm9mMmtIF9paZQPABovSl/b5uE0ijm3fAhD7aSa1Y8dLqo00bRYMN61OUdeXweZmR Yc2q+gNBtbQJaJrH3Acyta2ZXmlEf9bzPynHFEs55kqMqob/81Z40yaSKC6RhBcgqjhtNEnMF +9XmOmh Received-SPF: permerror client-ip=212.227.126.130; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" Signed-off-by: Laurent Vivier Reviewed-by: Stefano Brivio Reviewed-by: David Gibson Acked-by: Michael S. Tsirkin Acked-by: Markus Armbruster --- net/dgram.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++- qapi/net.json | 2 +- qemu-options.hx | 1 + 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/net/dgram.c b/net/dgram.c index e581cc62f39f..02a189e36358 100644 --- a/net/dgram.c +++ b/net/dgram.c @@ -426,6 +426,7 @@ int net_init_dgram(const Netdev *netdev, const char *name, SocketAddress *remote, *local; struct sockaddr *dest_addr; struct sockaddr_in laddr_in, raddr_in; + struct sockaddr_un laddr_un, raddr_un; socklen_t dest_len; assert(netdev->type == NET_CLIENT_DRIVER_DGRAM); @@ -465,7 +466,7 @@ int net_init_dgram(const Netdev *netdev, const char *name, } } else { if (local->type != SOCKET_ADDRESS_TYPE_FD) { - error_setg(errp, "type=inet requires remote parameter"); + error_setg(errp, "type=inet or unix require remote parameter"); return -1; } } @@ -508,6 +509,53 @@ int net_init_dgram(const Netdev *netdev, const char *name, dest_addr = g_malloc(dest_len); memcpy(dest_addr, &raddr_in, dest_len); break; + case SOCKET_ADDRESS_TYPE_UNIX: + ret = unlink(local->u.q_unix.path); + if (ret < 0 && errno != ENOENT) { + error_setg_errno(errp, errno, "failed to unlink socket %s", + local->u.q_unix.path); + return -1; + } + + laddr_un.sun_family = PF_UNIX; + ret = snprintf(laddr_un.sun_path, sizeof(laddr_un.sun_path), "%s", + local->u.q_unix.path); + if (ret < 0 || ret >= sizeof(laddr_un.sun_path)) { + error_setg(errp, "UNIX socket path '%s' is too long", + local->u.q_unix.path); + error_append_hint(errp, "Path must be less than %zu bytes\n", + sizeof(laddr_un.sun_path)); + } + + raddr_un.sun_family = PF_UNIX; + ret = snprintf(raddr_un.sun_path, sizeof(raddr_un.sun_path), "%s", + remote->u.q_unix.path); + if (ret < 0 || ret >= sizeof(raddr_un.sun_path)) { + error_setg(errp, "UNIX socket path '%s' is too long", + remote->u.q_unix.path); + error_append_hint(errp, "Path must be less than %zu bytes\n", + sizeof(raddr_un.sun_path)); + } + + fd = qemu_socket(PF_UNIX, SOCK_DGRAM, 0); + if (fd < 0) { + error_setg_errno(errp, errno, "can't create datagram socket"); + return -1; + } + + ret = bind(fd, (struct sockaddr *)&laddr_un, sizeof(laddr_un)); + if (ret < 0) { + error_setg_errno(errp, errno, "can't bind unix=%s to socket", + laddr_un.sun_path); + closesocket(fd); + return -1; + } + qemu_socket_set_nonblock(fd); + + dest_len = sizeof(raddr_un); + dest_addr = g_malloc(dest_len); + memcpy(dest_addr, &raddr_un, dest_len); + break; case SOCKET_ADDRESS_TYPE_FD: fd = monitor_fd_param(monitor_cur(), local->u.fd.str, errp); if (fd == -1) { @@ -546,6 +594,10 @@ int net_init_dgram(const Netdev *netdev, const char *name, inet_ntoa(raddr_in.sin_addr), ntohs(raddr_in.sin_port)); break; + case SOCKET_ADDRESS_TYPE_UNIX: + qemu_set_info_str(&s->nc, "udp=%s:%s", + laddr_un.sun_path, raddr_un.sun_path); + break; case SOCKET_ADDRESS_TYPE_FD: { SocketAddress *sa; SocketAddressType sa_type; diff --git a/qapi/net.json b/qapi/net.json index a85eddcaed92..6a1a49749294 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -600,7 +600,7 @@ # @remote: remote address # @local: local address # -# Only SocketAddress types 'inet' and 'fd' are supported. +# Only SocketAddress types 'unix', 'inet' and 'fd' are supported. # # If remote address is present and it's a multicast address, local address # is optional. Otherwise local address is required and remote address is diff --git a/qemu-options.hx b/qemu-options.hx index 242c45e44af3..e7fc7a8e4c12 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2766,6 +2766,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, " configure a network backend to connect to a multicast maddr and port\n" " use ``local.host=addr`` to specify the host address to send packets from\n" "-netdev dgram,id=str,local.type=inet,local.host=addr,local.port=port[,remote.type=inet,remote.host=addr,remote.port=port]\n" + "-netdev dgram,id=str,local.type=unix,local.path=path[,remote.type=unix,remote.path=path]\n" "-netdev dgram,id=str,local.type=fd,local.str=file-descriptor\n" " configure a network backend to connect to another network\n" " using an UDP tunnel\n" From patchwork Tue Oct 11 20:05:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004325 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 D6272C433F5 for ; Tue, 11 Oct 2022 20:37:13 +0000 (UTC) Received: from localhost ([::1]:35762 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLzz-0007wj-NI for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:37:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39964) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLW4-0006Qi-RI for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:21 -0400 Received: from mout.kundenserver.de ([212.227.126.130]:47915) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLW2-0003m6-V2 for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:16 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MTRAS-1oabDc13xU-00TjMO; Tue, 11 Oct 2022 22:06:04 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org Subject: [PATCH v11 13/17] qemu-sockets: move and rename SocketAddress_to_str() Date: Tue, 11 Oct 2022 22:05:35 +0200 Message-Id: <20221011200539.1486809-14-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:hUbb5jIwSKgK+St/SNdQdxrOCLG2qz2KV1mFxYpohHUQ+jMosg+ /HKFutYpgagnW/am+mHnu3RmkjMsfIuCe/IxM+S1ZR3Q+JbKxF7+jV6//HGRE/lEOpsqOy+ 63lfkFOZAfQUA3XvVa6rO7MRcpD3VG4Zs3OCp2PQHuWhqKiPAGUDxGcGG5dy6zKc05Vzrkm JKcp0NVOePxWqhJy1cTRw== X-UI-Out-Filterresults: notjunk:1;V03:K0:EdrdNw6kAng=:zUwUpnsZ9dtTDBann7xlY+ NabQ9aeQyi8QsRjB/y76X5TCg7K0qLZoNLpz8mM7Zo3ZQhJIApD9C9aDC1EolJWBYxQJ/V1/H RlLNm9gPN5Rn4dO8CSVnwdV2b3LDbhLTeKCyJKbEibC4HvRc0HaE8TAUgUY5xpUdG9yJOHLW1 Gfhx2pPGT+flDO3jwk1pFyMfGuMTzVWbPPM7c/iDUT8r6eWtdJirZIbUcS9DDHEUhB7ESnh10 UhI3QS7Gr11Pc20zN2giyZfDyGJt2wph3fxrNF+yzoc452MPrsL2/h4U7sOdFJW921dBGIaa7 cpNKJIUPPhWwDPtfkNsIuF2pmYOI5ogd4pH6eCDtd8NVZ2OduTDLK2aXbBwPMtgrphC8RAzXa Ntc5WAY4xN4aaGZaOpFqX1uPnleaIuddr33+CPN4vcU1MRz1slITSloFcwwbRo1ttNpbzotXY g/zlOTwnzWifk3cajdYCNo6jzJu3kxNLQDWTHzsUXwJsbjpC/romBLDSCL34Y6TM/NqpeqYDH fBvxJ3/Vo5I3YdBg2ApkLlhZj5gl8NucvlsLvBNbPFOUoHA3ZMCQmMn0pt/vNyfvDKeQCor60 erildVWMVQuyM1uJpz3AgOrJixYQ9vh1sSHRonDC60IP3U+kTY8gSkbm06xGArDYjJeja3KMg iZYkjYLYLmbNQUIxOCmo3MuXRHGCmOR/mMUE/YymNFzbag+G5eM7jZRPDYj4Lm+LrLe9Z5gm5 EVigbZXKRYei88JPcpvgXDhNGXLb9ejh1ozMaBvJnTkCAAET4wtmOzonmvk8QNpB0V2Arxwvp zS8qlj5 Received-SPF: permerror client-ip=212.227.126.130; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" Rename SocketAddress_to_str() to socket_uri() and move it to util/qemu-sockets.c close to socket_parse(). socket_uri() generates a string from a SocketAddress while socket_parse() generates a SocketAddress from a string. Signed-off-by: Laurent Vivier Reviewed-by: David Gibson Reviewed-by: Dr. David Alan Gilbert Acked-by: Michael S. Tsirkin --- include/qemu/sockets.h | 2 +- monitor/hmp-cmds.c | 23 +---------------------- util/qemu-sockets.c | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index db4bedb6fa20..214058d8e307 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -58,6 +58,7 @@ NetworkAddressFamily inet_netfamily(int family); int unix_listen(const char *path, Error **errp); int unix_connect(const char *path, Error **errp); +char *socket_uri(SocketAddress *addr); SocketAddress *socket_parse(const char *str, Error **errp); int socket_connect(SocketAddress *addr, Error **errp); int socket_listen(SocketAddress *addr, int num, Error **errp); @@ -141,5 +142,4 @@ SocketAddress *socket_address_flatten(SocketAddressLegacy *addr); * Return 0 on success. */ int socket_address_parse_named_fd(SocketAddress *addr, Error **errp); - #endif /* QEMU_SOCKETS_H */ diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index f90eea8d01c6..edf7068a9224 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -197,27 +197,6 @@ void hmp_info_mice(Monitor *mon, const QDict *qdict) qapi_free_MouseInfoList(mice_list); } -static char *SocketAddress_to_str(SocketAddress *addr) -{ - switch (addr->type) { - case SOCKET_ADDRESS_TYPE_INET: - return g_strdup_printf("tcp:%s:%s", - addr->u.inet.host, - addr->u.inet.port); - case SOCKET_ADDRESS_TYPE_UNIX: - return g_strdup_printf("unix:%s", - addr->u.q_unix.path); - case SOCKET_ADDRESS_TYPE_FD: - return g_strdup_printf("fd:%s", addr->u.fd.str); - case SOCKET_ADDRESS_TYPE_VSOCK: - return g_strdup_printf("tcp:%s:%s", - addr->u.vsock.cid, - addr->u.vsock.port); - default: - return g_strdup("unknown address type"); - } -} - void hmp_info_migrate(Monitor *mon, const QDict *qdict) { MigrationInfo *info; @@ -380,7 +359,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) monitor_printf(mon, "socket address: [\n"); for (addr = info->socket_address; addr; addr = addr->next) { - char *s = SocketAddress_to_str(addr->value); + char *s = socket_uri(addr->value); monitor_printf(mon, "\t%s\n", s); g_free(s); } diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 83f4bd6fd211..9f6f655fd526 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -1077,6 +1077,26 @@ int unix_connect(const char *path, Error **errp) return sock; } +char *socket_uri(SocketAddress *addr) +{ + switch (addr->type) { + case SOCKET_ADDRESS_TYPE_INET: + return g_strdup_printf("tcp:%s:%s", + addr->u.inet.host, + addr->u.inet.port); + case SOCKET_ADDRESS_TYPE_UNIX: + return g_strdup_printf("unix:%s", + addr->u.q_unix.path); + case SOCKET_ADDRESS_TYPE_FD: + return g_strdup_printf("fd:%s", addr->u.fd.str); + case SOCKET_ADDRESS_TYPE_VSOCK: + return g_strdup_printf("tcp:%s:%s", + addr->u.vsock.cid, + addr->u.vsock.port); + default: + return g_strdup("unknown address type"); + } +} SocketAddress *socket_parse(const char *str, Error **errp) { From patchwork Tue Oct 11 20:05:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004315 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 C22B5C433FE for ; Tue, 11 Oct 2022 20:17:06 +0000 (UTC) Received: from localhost ([::1]:38950 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLgX-0008O6-QD for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:17:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60960) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLWP-0006TC-4n for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:38 -0400 Received: from mout.kundenserver.de ([212.227.126.134]:49327) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLWM-0003mu-VE for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:36 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1Mow4E-1pWINf2lw6-00qT0M; Tue, 11 Oct 2022 22:06:05 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org Subject: [PATCH v11 14/17] qemu-sockets: update socket_uri() and socket_parse() to be consistent Date: Tue, 11 Oct 2022 22:05:36 +0200 Message-Id: <20221011200539.1486809-15-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:ey0Bb/M2Z6F/4rYMomeFku/q8uwdpNMAl8SJ1jirWX+TzOcfMvc C4KO5r754mdDxXvdeYX20ijKUgPucKg/ixxH0Sw7PjdFSZ2DcBeD/I8FpLvnvtoQHKUQw8h YTynCh7urNtjxP+WDb+wVvbIAR0RJ0vpp/w6KEfVsrh4V5Eo5mqT8RuL40YD9wKD4oDe0Jd wW9K/RD0rgAcSHHFQvNHQ== X-UI-Out-Filterresults: notjunk:1;V03:K0:+1PMrstufmY=:k4HfV+kqjAzzgqeMBOLfwE rD5yjo3Bnu718rEHlAcZEo0BqD+Oj2TQ/ZHF145z0+kw58k7Qikfo15Gobs9IEmLB3B58Ynnh Adt8Il9Kw1OOOani8YoI4lshGo22uUoMcT433R5voB87FDrOKndu9uCvhzYjZK8Ci8PgviSGN 5MDpebMBUlQ1t2jmteIGpgSIIcRE4zi96AFURP15ZX4kwf4ZMKImuq3jJufRy6T/DWm8kO0UL s9ZuD17P4jjY6oqhsFCGS37Lb2BYfEs4zak/GCMuQT72qFU4MS2DpYxQe/AUzULU8IJU8zmHx hAtrbsmvHr50Xvb3sIoDbwHTQpZcTrzjShuPeslXWe3RVWXjzA50RqBtMQeGp/n8ySGsbnwIz mzU8iM6yR10qponNKd5ZCHcODA9D+k90aoOGh0nPRCSDAybgN5uEIbm3axB5j0ptC5/jHST4t yXoWCQnhuZbdHLaGFXeMWqtk1WMf+rjrkrtLss03FcRtacJepmqGAWsk/gKshx0UYGl6spw9x LORGN1465IrMCacVBNuYbQzX5CaQFtlA3FeYWcBWbfy1BGpSwwx0APY8zQ+xSwrov5XJkgSj9 OSx2rmPOylVK3oe7SrygDb3rTtxGhTUxa0LkyEfvAdIxKUD9LwThOPN+oD8LPvsd9v6t0Hb8+ u/Rpw99dVZcCqgscSxsXfEZphWb3ihn9AxRS8bdI/NDlWUwJ3ML80dNfbyvf6k+OAH+YQMhx7 kQo9yi2s5XsyoRX1pEzAKCJVqtpvGSDY6/rGTtF1pFsUBUmX5G75Tyn540SG+z/gKiI9YAD6r OXmyRDr Received-SPF: permerror client-ip=212.227.126.134; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" To be consistent with socket_uri(), add 'tcp:' prefix for inet type in socket_parse(), by default socket_parse() use tcp when no prefix is provided (format is host:port). In socket_uri(), use 'vsock:' prefix for vsock type rather than 'tcp:' because it makes a vsock address look like an inet address with CID misinterpreted as host. Goes back to commit 9aca82ba31 "migration: Create socket-address parameter" Signed-off-by: Laurent Vivier Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Markus Armbruster Reviewed-by: David Gibson Acked-by: Michael S. Tsirkin --- util/qemu-sockets.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 9f6f655fd526..a9926af714c4 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -1090,7 +1090,7 @@ char *socket_uri(SocketAddress *addr) case SOCKET_ADDRESS_TYPE_FD: return g_strdup_printf("fd:%s", addr->u.fd.str); case SOCKET_ADDRESS_TYPE_VSOCK: - return g_strdup_printf("tcp:%s:%s", + return g_strdup_printf("vsock:%s:%s", addr->u.vsock.cid, addr->u.vsock.port); default: @@ -1124,6 +1124,11 @@ SocketAddress *socket_parse(const char *str, Error **errp) if (vsock_parse(&addr->u.vsock, str + strlen("vsock:"), errp)) { goto fail; } + } else if (strstart(str, "tcp:", NULL)) { + addr->type = SOCKET_ADDRESS_TYPE_INET; + if (inet_parse(&addr->u.inet, str + strlen("tcp:"), errp)) { + goto fail; + } } else { addr->type = SOCKET_ADDRESS_TYPE_INET; if (inet_parse(&addr->u.inet, str, errp)) { From patchwork Tue Oct 11 20:05:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004326 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 CDD58C4332F for ; Tue, 11 Oct 2022 20:40:09 +0000 (UTC) Received: from localhost ([::1]:34764 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiM2q-0004NG-TU for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:40:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60962) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLWP-0006TD-5a for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:38 -0400 Received: from mout.kundenserver.de ([212.227.126.130]:51713) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLWL-0003mR-BY for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:36 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N63mC-1pFBEl0MAq-016LQi; Tue, 11 Oct 2022 22:06:07 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org Subject: [PATCH v11 15/17] net: stream: move to QIO to enable additional parameters Date: Tue, 11 Oct 2022 22:05:37 +0200 Message-Id: <20221011200539.1486809-16-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:7vXaqjbRGmqgWmePWhTFy3gBFGbDitEgkc56HQwcAPIQJuZSp2Y 1+2XArXj48v9Zz+UyE/7EvHNbZNwCN+pjJrlUEjXIMvuA+CXn5hEjV7h+ZpkXPNTjy2wHyn aXyhNBPCp4QpeuTCdXJbf7qVsXU5AZSmptzlZYrq/G3Ut7oCvWL2eOGiMvA0/PrIVN3TOxd g03aVAWZ85DofZDbppUPg== X-UI-Out-Filterresults: notjunk:1;V03:K0:tv+a5GfPxPc=:kTueZfycOoXSy8A3jt/HVM zSLsIZI+Eru1qQFCfmxN3JfKo+UeQ+0ZBE6yoMVJcjBDwvRGpGhmHoLtNgDSGULthLErqpbSO riBHxSctuNQwLVxzc44FJHwH/7jK2i7d8lsGDGpAV6NgLFNqMglhz6sNjYjUKCaMDJu80xgxl z9pUV7xp6op5tGoBE3qFtzb39zyRZcdNnut3GFNYJ/vOWTGLpU0NurmuuUBkzJsuPdwCE0fAq P9PGwAztBXYe4AxoomYm84hAycQH2Inly727Z2Ybst4vcHwQ2u8tL+fWPTzj9HSpjwGeu/ORi 6QPxEU++95bIUtoLvwPAPS09hjzE/N7Cwvfc6ZvdXY7HOOagWhH1sPa95Ak6r5AUrdiIfhwr9 aRgkQKxwIlW47wNKQqJGlRojojjP5cm69Ylw5eqFtwV0pzv75Pqa+otRUTsKHfSomR0tGCUyt f8k+hBLvuIFu0cQxL6jZdI2DOnvkJYwhknrFbgKE4jp1oqORfYRcggBMN12hvpyGWTyhFX/S0 GdUdiaOawfa2tgZfffM+raDgFyYqXl5VXv7Y/AkFxopUAKOSPnXna3g4oZJr/NisK2Y6qMbSy U6fCsLJp4dqCHKRXhYedusE6nHuN5HMzruwx6NeVS3GM0akgmP58gNxpJe/2iJNU/E40CFHxx Xpf5Tw3zBbJcmUkRDgN/V3Q3/Y36K+ATuM7xbrYAABD9zb4f5gpdZNhK1dmnZcdMXMYRkjWN5 OMHgQJBkyw/gJlJS2YCaAIulk+N8243JBygzC+uN4barn/oVhpajlX9ROAs2kN2FJEZuQfMCl zfQlVh2 Received-SPF: permerror client-ip=212.227.126.130; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" Use QIOChannel, QIOChannelSocket and QIONetListener. This allows net/stream to use all the available parameters provided by SocketAddress. Signed-off-by: Laurent Vivier Acked-by: Michael S. Tsirkin --- meson | 2 +- net/stream.c | 493 +++++++++++++++++------------------------------- qemu-options.hx | 4 +- 3 files changed, 180 insertions(+), 319 deletions(-) diff --git a/meson b/meson index 3a9b285a55b9..12f9f04ba0de 160000 --- a/meson +++ b/meson @@ -1 +1 @@ -Subproject commit 3a9b285a55b91b53b2acda987192274352ecb5be +Subproject commit 12f9f04ba0decfda425dbbf9a501084c153a2d18 diff --git a/net/stream.c b/net/stream.c index d26c79d035fc..0293e38e5b57 100644 --- a/net/stream.c +++ b/net/stream.c @@ -35,48 +35,36 @@ #include "qemu/iov.h" #include "qemu/main-loop.h" #include "qemu/cutils.h" +#include "io/channel.h" +#include "io/channel-socket.h" +#include "io/net-listener.h" typedef struct NetStreamState { NetClientState nc; - int listen_fd; - int fd; + QIOChannel *listen_ioc; + QIONetListener *listener; + QIOChannel *ioc; + guint ioc_read_tag; + guint ioc_write_tag; SocketReadState rs; unsigned int send_index; /* number of bytes sent*/ - bool read_poll; /* waiting to receive data? */ - bool write_poll; /* waiting to transmit data? */ } NetStreamState; -static void net_stream_send(void *opaque); -static void net_stream_accept(void *opaque); -static void net_stream_writable(void *opaque); +static void net_stream_listen(QIONetListener *listener, + QIOChannelSocket *cioc, + void *opaque); -static void net_stream_update_fd_handler(NetStreamState *s) +static gboolean net_stream_writable(QIOChannel *ioc, + GIOCondition condition, + gpointer data) { - qemu_set_fd_handler(s->fd, - s->read_poll ? net_stream_send : NULL, - s->write_poll ? net_stream_writable : NULL, - s); -} - -static void net_stream_read_poll(NetStreamState *s, bool enable) -{ - s->read_poll = enable; - net_stream_update_fd_handler(s); -} - -static void net_stream_write_poll(NetStreamState *s, bool enable) -{ - s->write_poll = enable; - net_stream_update_fd_handler(s); -} - -static void net_stream_writable(void *opaque) -{ - NetStreamState *s = opaque; + NetStreamState *s = data; - net_stream_write_poll(s, false); + s->ioc_write_tag = 0; qemu_flush_queued_packets(&s->nc); + + return G_SOURCE_REMOVE; } static ssize_t net_stream_receive(NetClientState *nc, const uint8_t *buf, @@ -93,13 +81,15 @@ static ssize_t net_stream_receive(NetClientState *nc, const uint8_t *buf, .iov_len = size, }, }; + struct iovec local_iov[2]; + unsigned int nlocal_iov; size_t remaining; ssize_t ret; remaining = iov_size(iov, 2) - s->send_index; - ret = iov_send(s->fd, iov, 2, s->send_index, remaining); - - if (ret == -1 && errno == EAGAIN) { + nlocal_iov = iov_copy(local_iov, 2, iov, 2, s->send_index, remaining); + ret = qio_channel_writev(s->ioc, local_iov, nlocal_iov, NULL); + if (ret == QIO_CHANNEL_ERR_BLOCK) { ret = 0; /* handled further down */ } if (ret == -1) { @@ -108,19 +98,25 @@ static ssize_t net_stream_receive(NetClientState *nc, const uint8_t *buf, } if (ret < (ssize_t)remaining) { s->send_index += ret; - net_stream_write_poll(s, true); + s->ioc_write_tag = qio_channel_add_watch(s->ioc, G_IO_OUT, + net_stream_writable, s, NULL); return 0; } s->send_index = 0; return size; } +static gboolean net_stream_send(QIOChannel *ioc, + GIOCondition condition, + gpointer data); + static void net_stream_send_completed(NetClientState *nc, ssize_t len) { NetStreamState *s = DO_UPCAST(NetStreamState, nc, nc); - if (!s->read_poll) { - net_stream_read_poll(s, true); + if (!s->ioc_read_tag) { + s->ioc_read_tag = qio_channel_add_watch(s->ioc, G_IO_IN, + net_stream_send, s, NULL); } } @@ -131,19 +127,24 @@ static void net_stream_rs_finalize(SocketReadState *rs) if (qemu_send_packet_async(&s->nc, rs->buf, rs->packet_len, net_stream_send_completed) == 0) { - net_stream_read_poll(s, false); + if (s->ioc_read_tag) { + g_source_remove(s->ioc_read_tag); + s->ioc_read_tag = 0; + } } } -static void net_stream_send(void *opaque) +static gboolean net_stream_send(QIOChannel *ioc, + GIOCondition condition, + gpointer data) { - NetStreamState *s = opaque; + NetStreamState *s = data; int size; int ret; - uint8_t buf1[NET_BUFSIZE]; - const uint8_t *buf; + char buf1[NET_BUFSIZE]; + const char *buf; - size = recv(s->fd, buf1, sizeof(buf1), 0); + size = qio_channel_read(s->ioc, buf1, sizeof(buf1), NULL); if (size < 0) { if (errno != EWOULDBLOCK) { goto eoc; @@ -151,51 +152,63 @@ static void net_stream_send(void *opaque) } else if (size == 0) { /* end of connection */ eoc: - net_stream_read_poll(s, false); - net_stream_write_poll(s, false); - if (s->listen_fd != -1) { - qemu_set_fd_handler(s->listen_fd, net_stream_accept, NULL, s); + s->ioc_read_tag = 0; + if (s->ioc_write_tag) { + g_source_remove(s->ioc_write_tag); + s->ioc_write_tag = 0; } - closesocket(s->fd); + if (s->listener) { + qio_net_listener_set_client_func(s->listener, net_stream_listen, + s, NULL); + } + object_unref(OBJECT(s->ioc)); + s->ioc = NULL; - s->fd = -1; net_socket_rs_init(&s->rs, net_stream_rs_finalize, false); s->nc.link_down = true; qemu_set_info_str(&s->nc, ""); - return; + return G_SOURCE_REMOVE; } buf = buf1; - ret = net_fill_rstate(&s->rs, buf, size); + ret = net_fill_rstate(&s->rs, (const uint8_t *)buf, size); if (ret == -1) { goto eoc; } + + return G_SOURCE_CONTINUE; } static void net_stream_cleanup(NetClientState *nc) { NetStreamState *s = DO_UPCAST(NetStreamState, nc, nc); - if (s->fd != -1) { - net_stream_read_poll(s, false); - net_stream_write_poll(s, false); - close(s->fd); - s->fd = -1; + if (s->ioc) { + if (QIO_CHANNEL_SOCKET(s->ioc)->fd != -1) { + if (s->ioc_read_tag) { + g_source_remove(s->ioc_read_tag); + s->ioc_read_tag = 0; + } + if (s->ioc_write_tag) { + g_source_remove(s->ioc_write_tag); + s->ioc_write_tag = 0; + } + } + object_unref(OBJECT(s->ioc)); + s->ioc = NULL; } - if (s->listen_fd != -1) { - qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); - closesocket(s->listen_fd); - s->listen_fd = -1; + if (s->listen_ioc) { + if (s->listener) { + qio_net_listener_disconnect(s->listener); + object_unref(OBJECT(s->listener)); + s->listener = NULL; + } + object_unref(OBJECT(s->listen_ioc)); + s->listen_ioc = NULL; } } -static void net_stream_connect(void *opaque) -{ - NetStreamState *s = opaque; - net_stream_read_poll(s, true); -} - static NetClientInfo net_stream_info = { .type = NET_CLIENT_DRIVER_STREAM, .size = sizeof(NetStreamState), @@ -203,76 +216,67 @@ static NetClientInfo net_stream_info = { .cleanup = net_stream_cleanup, }; -static NetStreamState *net_stream_fd_init(NetClientState *peer, - const char *model, - const char *name, - int fd, int is_connected) +static void net_stream_listen(QIONetListener *listener, + QIOChannelSocket *cioc, + void *opaque) { - NetClientState *nc; - NetStreamState *s; - - nc = qemu_new_net_client(&net_stream_info, peer, model, name); + NetStreamState *s = opaque; + SocketAddress *addr; + char *uri; - qemu_set_info_str(nc, "fd=%d", fd); + object_ref(OBJECT(cioc)); - s = DO_UPCAST(NetStreamState, nc, nc); + qio_net_listener_set_client_func(s->listener, NULL, s, NULL); - s->fd = fd; - s->listen_fd = -1; - net_socket_rs_init(&s->rs, net_stream_rs_finalize, false); + s->ioc = QIO_CHANNEL(cioc); + qio_channel_set_name(s->ioc, "stream-server"); + s->nc.link_down = false; - /* Disable Nagle algorithm on TCP sockets to reduce latency */ - socket_set_nodelay(fd); + s->ioc_read_tag = qio_channel_add_watch(s->ioc, G_IO_IN, net_stream_send, + s, NULL); - if (is_connected) { - net_stream_connect(s); + if (cioc->localAddr.ss_family == AF_UNIX) { + addr = qio_channel_socket_get_local_address(cioc, NULL); } else { - qemu_set_fd_handler(s->fd, NULL, net_stream_connect, s); + addr = qio_channel_socket_get_remote_address(cioc, NULL); } - return s; + g_assert(addr != NULL); + uri = socket_uri(addr); + qemu_set_info_str(&s->nc, uri); + g_free(uri); + qapi_free_SocketAddress(addr); + } -static void net_stream_accept(void *opaque) +static void net_stream_server_listening(QIOTask *task, gpointer opaque) { NetStreamState *s = opaque; - struct sockaddr_storage saddr; - socklen_t len; - int fd; - - for (;;) { - len = sizeof(saddr); - fd = qemu_accept(s->listen_fd, (struct sockaddr *)&saddr, &len); - if (fd < 0 && errno != EINTR) { - return; - } else if (fd >= 0) { - qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); - break; - } - } + QIOChannelSocket *listen_sioc = QIO_CHANNEL_SOCKET(s->listen_ioc); + SocketAddress *addr; + int ret; - s->fd = fd; - s->nc.link_down = false; - net_stream_connect(s); - switch (saddr.ss_family) { - case AF_INET: { - struct sockaddr_in *saddr_in = (struct sockaddr_in *)&saddr; - - qemu_set_info_str(&s->nc, "connection from %s:%d", - inet_ntoa(saddr_in->sin_addr), - ntohs(saddr_in->sin_port)); - break; + if (listen_sioc->fd < 0) { + qemu_set_info_str(&s->nc, "connection error"); + return; } - case AF_UNIX: { - struct sockaddr_un saddr_un; - len = sizeof(saddr_un); - getsockname(s->listen_fd, (struct sockaddr *)&saddr_un, &len); - qemu_set_info_str(&s->nc, "connect from %s", saddr_un.sun_path); - break; - } - default: - g_assert_not_reached(); + addr = qio_channel_socket_get_local_address(listen_sioc, NULL); + g_assert(addr != NULL); + ret = qemu_socket_try_set_nonblock(listen_sioc->fd); + if (addr->type == SOCKET_ADDRESS_TYPE_FD && ret < 0) { + qemu_set_info_str(&s->nc, "can't use file descriptor %s (errno %d)", + addr->u.fd.str, -ret); + return; } + g_assert(ret == 0); + qapi_free_SocketAddress(addr); + + s->nc.link_down = true; + s->listener = qio_net_listener_new(); + + net_socket_rs_init(&s->rs, net_stream_rs_finalize, false); + qio_net_listener_set_client_func(s->listener, net_stream_listen, s, NULL); + qio_net_listener_add(s->listener, listen_sioc); } static int net_stream_server_init(NetClientState *peer, @@ -283,105 +287,61 @@ static int net_stream_server_init(NetClientState *peer, { NetClientState *nc; NetStreamState *s; - int fd, ret; - - switch (addr->type) { - case SOCKET_ADDRESS_TYPE_INET: { - struct sockaddr_in saddr_in; - - if (convert_host_port(&saddr_in, addr->u.inet.host, addr->u.inet.port, - errp) < 0) { - return -1; - } + QIOChannelSocket *listen_sioc = qio_channel_socket_new(); - fd = qemu_socket(PF_INET, SOCK_STREAM, 0); - if (fd < 0) { - error_setg_errno(errp, errno, "can't create stream socket"); - return -1; - } - qemu_socket_set_nonblock(fd); + nc = qemu_new_net_client(&net_stream_info, peer, model, name); + s = DO_UPCAST(NetStreamState, nc, nc); - socket_set_fast_reuse(fd); + s->listen_ioc = QIO_CHANNEL(listen_sioc); + qio_channel_socket_listen_async(listen_sioc, addr, 0, + net_stream_server_listening, s, + NULL, NULL); - ret = bind(fd, (struct sockaddr *)&saddr_in, sizeof(saddr_in)); - if (ret < 0) { - error_setg_errno(errp, errno, "can't bind ip=%s to socket", - inet_ntoa(saddr_in.sin_addr)); - closesocket(fd); - return -1; - } - break; - } - case SOCKET_ADDRESS_TYPE_UNIX: { - struct sockaddr_un saddr_un; - - ret = unlink(addr->u.q_unix.path); - if (ret < 0 && errno != ENOENT) { - error_setg_errno(errp, errno, "failed to unlink socket %s", - addr->u.q_unix.path); - return -1; - } + return 0; +} - saddr_un.sun_family = PF_UNIX; - ret = snprintf(saddr_un.sun_path, sizeof(saddr_un.sun_path), "%s", - addr->u.q_unix.path); - if (ret < 0 || ret >= sizeof(saddr_un.sun_path)) { - error_setg(errp, "UNIX socket path '%s' is too long", - addr->u.q_unix.path); - error_append_hint(errp, "Path must be less than %zu bytes\n", - sizeof(saddr_un.sun_path)); - return -1; - } +static void net_stream_client_connected(QIOTask *task, gpointer opaque) +{ + NetStreamState *s = opaque; + QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(s->ioc); + SocketAddress *addr; + gchar *uri; + int ret; - fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0); - if (fd < 0) { - error_setg_errno(errp, errno, "can't create stream socket"); - return -1; - } - qemu_socket_set_nonblock(fd); - - ret = bind(fd, (struct sockaddr *)&saddr_un, sizeof(saddr_un)); - if (ret < 0) { - error_setg_errno(errp, errno, "can't create socket with path: %s", - saddr_un.sun_path); - closesocket(fd); - return -1; - } - break; - } - case SOCKET_ADDRESS_TYPE_FD: - fd = monitor_fd_param(monitor_cur(), addr->u.fd.str, errp); - if (fd == -1) { - return -1; - } - ret = qemu_socket_try_set_nonblock(fd); - if (ret < 0) { - error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", - name, fd); - return -1; - } - break; - default: - error_setg(errp, "only support inet or fd type"); - return -1; + if (sioc->fd < 0) { + qemu_set_info_str(&s->nc, "connection error"); + goto error; } - ret = listen(fd, 0); - if (ret < 0) { - error_setg_errno(errp, errno, "can't listen on socket"); - closesocket(fd); - return -1; + addr = qio_channel_socket_get_remote_address(sioc, NULL); + g_assert(addr != NULL); + uri = socket_uri(addr); + qemu_set_info_str(&s->nc, uri); + g_free(uri); + + ret = qemu_socket_try_set_nonblock(sioc->fd); + if (addr->type == SOCKET_ADDRESS_TYPE_FD && ret < 0) { + qemu_set_info_str(&s->nc, "can't use file descriptor %s (errno %d)", + addr->u.fd.str, -ret); + qapi_free_SocketAddress(addr); + goto error; } + g_assert(ret == 0); + qapi_free_SocketAddress(addr); - nc = qemu_new_net_client(&net_stream_info, peer, model, name); - s = DO_UPCAST(NetStreamState, nc, nc); - s->fd = -1; - s->listen_fd = fd; - s->nc.link_down = true; net_socket_rs_init(&s->rs, net_stream_rs_finalize, false); - qemu_set_fd_handler(s->listen_fd, net_stream_accept, NULL, s); - return 0; + /* Disable Nagle algorithm on TCP sockets to reduce latency */ + qio_channel_set_delay(s->ioc, false); + + s->ioc_read_tag = qio_channel_add_watch(s->ioc, G_IO_IN, net_stream_send, + s, NULL); + s->nc.link_down = false; + + return; +error: + object_unref(OBJECT(s->ioc)); + s->ioc = NULL; } static int net_stream_client_init(NetClientState *peer, @@ -391,118 +351,19 @@ static int net_stream_client_init(NetClientState *peer, Error **errp) { NetStreamState *s; - struct sockaddr_in saddr_in; - struct sockaddr_un saddr_un; - int fd, connected, ret; - - switch (addr->type) { - case SOCKET_ADDRESS_TYPE_INET: - if (convert_host_port(&saddr_in, addr->u.inet.host, addr->u.inet.port, - errp) < 0) { - return -1; - } + NetClientState *nc; + QIOChannelSocket *sioc = qio_channel_socket_new(); - fd = qemu_socket(PF_INET, SOCK_STREAM, 0); - if (fd < 0) { - error_setg_errno(errp, errno, "can't create stream socket"); - return -1; - } - qemu_socket_set_nonblock(fd); - - connected = 0; - for (;;) { - ret = connect(fd, (struct sockaddr *)&saddr_in, sizeof(saddr_in)); - if (ret < 0) { - if (errno == EINTR || errno == EWOULDBLOCK) { - /* continue */ - } else if (errno == EINPROGRESS || - errno == EALREADY) { - break; - } else { - error_setg_errno(errp, errno, "can't connect socket"); - closesocket(fd); - return -1; - } - } else { - connected = 1; - break; - } - } - break; - case SOCKET_ADDRESS_TYPE_UNIX: - saddr_un.sun_family = PF_UNIX; - ret = snprintf(saddr_un.sun_path, sizeof(saddr_un.sun_path), "%s", - addr->u.q_unix.path); - if (ret < 0 || ret >= sizeof(saddr_un.sun_path)) { - error_setg(errp, "UNIX socket path '%s' is too long", - addr->u.q_unix.path); - error_append_hint(errp, "Path must be less than %zu bytes\n", - sizeof(saddr_un.sun_path)); - return -1; - } + nc = qemu_new_net_client(&net_stream_info, peer, model, name); + s = DO_UPCAST(NetStreamState, nc, nc); - fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0); - if (fd < 0) { - error_setg_errno(errp, errno, "can't create stream socket"); - return -1; - } - qemu_socket_set_nonblock(fd); - - connected = 0; - for (;;) { - ret = connect(fd, (struct sockaddr *)&saddr_un, sizeof(saddr_un)); - if (ret < 0) { - if (errno == EINTR || errno == EWOULDBLOCK) { - /* continue */ - } else if (errno == EAGAIN || - errno == EALREADY) { - break; - } else { - error_setg_errno(errp, errno, "can't connect socket"); - closesocket(fd); - return -1; - } - } else { - connected = 1; - break; - } - } - break; - case SOCKET_ADDRESS_TYPE_FD: - fd = monitor_fd_param(monitor_cur(), addr->u.fd.str, errp); - if (fd == -1) { - return -1; - } - ret = qemu_socket_try_set_nonblock(fd); - if (ret < 0) { - error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", - name, fd); - return -1; - } - connected = 1; - break; - default: - error_setg(errp, "only support inet, unix or fd type"); - return -1; - } + s->ioc = QIO_CHANNEL(sioc); + s->nc.link_down = true; + + qio_channel_socket_connect_async(sioc, addr, + net_stream_client_connected, s, + NULL, NULL); - s = net_stream_fd_init(peer, model, name, fd, connected); - - switch (addr->type) { - case SOCKET_ADDRESS_TYPE_INET: - qemu_set_info_str(&s->nc, "connect to %s:%d", - inet_ntoa(saddr_in.sin_addr), - ntohs(saddr_in.sin_port)); - break; - case SOCKET_ADDRESS_TYPE_UNIX: - qemu_set_info_str(&s->nc, " connect to %s", saddr_un.sun_path); - break; - case SOCKET_ADDRESS_TYPE_FD: - qemu_set_info_str(&s->nc, "connect to fd %d", fd); - break; - default: - g_assert_not_reached(); - } return 0; } diff --git a/qemu-options.hx b/qemu-options.hx index e7fc7a8e4c12..1bfdb4a8b29e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2756,8 +2756,8 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, "-netdev socket,id=str[,fd=h][,udp=host:port][,localaddr=host:port]\n" " configure a network backend to connect to another network\n" " using an UDP tunnel\n" - "-netdev stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port\n" - "-netdev stream,id=str[,server=on|off],addr.type=unix,addr.path=path\n" + "-netdev stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port[,to=maxport][,numeric=on|off][,keep-alive=on|off][,mptcp=on|off][,addr.ipv4=on|off][,addr.ipv6=on|off]\n" + "-netdev stream,id=str[,server=on|off],addr.type=unix,addr.path=path[,abstract=on|off][,tight=on|off]\n" "-netdev stream,id=str[,server=on|off],addr.type=fd,addr.str=file-descriptor\n" " configure a network backend to connect to another network\n" " using a socket connection in stream mode.\n" From patchwork Tue Oct 11 20:05:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004324 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 6DEC7C433FE for ; Tue, 11 Oct 2022 20:36:56 +0000 (UTC) Received: from localhost ([::1]:36078 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiLzi-0007Tu-61 for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:36:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60970) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLWR-0006TQ-3m for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:40 -0400 Received: from mout.kundenserver.de ([212.227.126.131]:59499) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLWN-0003nC-7W for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:38 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N32y5-1p9Nwj3EBZ-013LA1; Tue, 11 Oct 2022 22:06:09 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org Subject: [PATCH v11 16/17] tests/qtest: netdev: test stream and dgram backends Date: Tue, 11 Oct 2022 22:05:38 +0200 Message-Id: <20221011200539.1486809-17-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:RJBHOfXCnWbuHXI+J/jOEkoFW7ShFepPBrX3ec7hwHHPGeG8JdK rEuxrIG+kTQqx5QaoYMvDd0qhjLIWLsCQfMQ57s7il9o1ZGgoqRj+x+jeg3DNTSlUc89+at qE8xOdRU/SFStmsleJoQf+1HpwmZKnb6o/fxwuiqIkLh3NUFw7JD2lt6Yhsl2e5G56dKUpm uKIZfev54bXqoILRtYDGg== X-UI-Out-Filterresults: notjunk:1;V03:K0:2i6XrCzfqRs=:QHmxzJyycATjMXlf6gT2i+ 7zFkqo751SH3KulzD0sA9WCg5+l4LqdkKP8irk7pO3mkKLY2g2ieQrbN5IaVW3/oUOV6Qj/6C V7C0hmxuoorvWoqHzwVcAexAFoeARYTVZXxhq7+LJRSJ1+StDeuW7W8ZfgFId/sytgvMJw/bI BF6Ay+t9lnZ+1dj/kBCBuHwkAHYLQawCueBkAKVvQ+z4VuMf0CVKi5AjzzAOaM5scHR3k+OHw zQW6TUqnHWVbX4KTJRBS6ouQ5qeqBRcl4kIb1Dsc9+ORDJISugHplKh22e5XNdXVE+c9t55IW fKN1e4StGHYc/XXAlWv+bGUyiN+dn4pwT0HJB9JRyAnFAW8doWteHiQRtCnyaz91zRMUj38+q 4ac2TRoZUP6KLUmypLOFU4Jv25b7vMLdLgsvEWA/1rCDC7DBQRFs8wNWYaal6lEpj3s2eMiF/ ANcE8voQHDiqTHHG/pekpuNu8bN0wW01G4uijiMnYpoQ9ulgYrKW+HMSJaqHOoOBOafXNgxTH 2K5vbZkRDwtNh5kYXatRNk9bysGmbWm9jgdgjTK8Ni0qNdcwODuzdvS8jT2KZ3WBiA3lG0JKH SUr+0VFgbFNt0UzhIQov2wVJNmEe+dGIwgDatIFw2U5ouSRAXxwtEZscDOBxVuCxEWAgQnEZu je6sst00ugwc1e5eb/VKxvrZ5B3FhTORz5D+ZJUoCJ4claQTtQ2+uSnDs6WvgFl7iSc8Dz/// b78Eft7a6O3Nh5pfHYA1AK/Ke4TnQo2vJLLJOIEMa4iy14xPmT7Pcye/0pa1wXFsKZ5H1HiAJ WjX9puI Received-SPF: permerror client-ip=212.227.126.131; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" Signed-off-by: Laurent Vivier Acked-by: Michael S. Tsirkin --- tests/qtest/meson.build | 1 + tests/qtest/netdev-socket.c | 417 ++++++++++++++++++++++++++++++++++++ 2 files changed, 418 insertions(+) create mode 100644 tests/qtest/netdev-socket.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 455f1bbb7e52..464774e7b630 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' ] diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c new file mode 100644 index 000000000000..4ea66b4c6988 --- /dev/null +++ b/tests/qtest/netdev-socket.c @@ -0,0 +1,417 @@ +/* + * 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 "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 int inet_get_free_port_socket(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_multiple(int nb, int *port) +{ + int sock[nb]; + int i; + + for (i = 0; i < nb; i++) { + sock[i] = socket(AF_INET, SOCK_STREAM, 0); + if (sock[i] < 0) { + break; + } + port[i] = inet_get_free_port_socket(sock[i]); + } + + nb = i; + for (i = 0; i < nb; i++) { + closesocket(sock[i]); + } + + return nb; +} + +static int inet_get_free_port(void) +{ + int nb, port; + + nb = inet_get_free_port_multiple(1, &port); + 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(); + qts0 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,addr.type=inet," + "addr.ipv4=on,addr.ipv6=off," + "addr.host=localhost,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=localhost,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(); + qts0 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,addr.type=inet," + "addr.ipv4=off,addr.ipv6=on," + "addr.host=localhost,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=localhost,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; + int ret; + + ret = g_file_open_tmp("netdev-XXXXXX", &path, NULL); + g_assert_true(ret >= 0); + close(ret); + + qts0 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,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); + unlink(path); + g_free(path); + + qtest_quit(qts1); + qtest_quit(qts0); +} + +static void test_stream_unix_abstract(void) +{ + QTestState *qts0, *qts1; + char *expect; + gchar *path; + int ret; + + ret = g_file_open_tmp("netdev-XXXXXX", &path, NULL); + g_assert_true(ret >= 0); + close(ret); + + qts0 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,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); + unlink(path); + g_free(path); + + qtest_quit(qts1); + qtest_quit(qts0); +} + +static void test_stream_fd(void) +{ + QTestState *qts0, *qts1; + char *expect; + int ret, sock0, sock1; + struct sockaddr_un addr; + gchar *path; + + ret = g_file_open_tmp("netdev-XXXXXX", &path, NULL); + g_assert_true(ret >= 0); + close(ret); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, path); + + unlink(addr.sun_path); + sock0 = socket(AF_LOCAL, SOCK_STREAM, 0); + g_assert_cmpint(sock0, !=, -1); + + ret = bind(sock0, (struct sockaddr *)&addr, sizeof(addr)); + g_assert_cmpint(ret, !=, -1); + + qts0 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,addr.type=fd,addr.str=%d", + sock0); + + EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0); + + sock1 = socket(AF_LOCAL, SOCK_STREAM, 0); + g_assert_cmpint(sock1, !=, -1); + + ret = connect(sock1, (struct sockaddr *)&addr, sizeof(addr)); + g_assert_cmpint(ret, !=, -1); + + qts1 = qtest_initf("-nodefaults " + "-netdev stream,id=st0,server=off,addr.type=fd,addr.str=%d", + sock1); + + + 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); + + qtest_quit(qts1); + qtest_quit(qts0); + + closesocket(sock0); + closesocket(sock1); + + g_free(path); +} + +static void test_dgram_inet(void) +{ + QTestState *qts0, *qts1; + char *expect; + int port[2]; + int nb; + + nb = inet_get_free_port_multiple(2, port); + g_assert_cmpint(nb, ==, 2); + + qts0 = qtest_initf("-nodefaults " + "-netdev dgram,id=st0," + "local.type=inet,local.host=localhost,local.port=%d," + "remote.type=inet,remote.host=localhost,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=localhost,local.port=%d," + "remote.type=inet,remote.host=localhost,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; + int ret; + + ret = g_file_open_tmp("netdev-XXXXXX", &path0, NULL); + g_assert_true(ret >= 0); + close(ret); + + ret = g_file_open_tmp("netdev-XXXXXX", &path1, NULL); + g_assert_true(ret >= 0); + close(ret); + + 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; + + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/netdev/stream/inet/ipv4", test_stream_inet_ipv4); + qtest_add_func("/netdev/stream/inet/ipv6", test_stream_inet_ipv6); + 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/inet", test_dgram_inet); + qtest_add_func("/netdev/dgram/mcast", test_dgram_mcast); + qtest_add_func("/netdev/dgram/unix", test_dgram_unix); + qtest_add_func("/netdev/dgram/fd", test_dgram_fd); + + ret = g_test_run(); + + return ret; +} From patchwork Tue Oct 11 20:05:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13004327 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 01D03C433FE for ; Tue, 11 Oct 2022 20:40:52 +0000 (UTC) Received: from localhost ([::1]:41608 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oiM3X-00053V-RU for qemu-devel@archiver.kernel.org; Tue, 11 Oct 2022 16:40:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60972) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLWR-0006TR-5r for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:40 -0400 Received: from mout.kundenserver.de ([212.227.126.130]:54521) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oiLWO-0003n1-PQ for qemu-devel@nongnu.org; Tue, 11 Oct 2022 16:06:38 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MkYLW-1pRsXE1Tsk-00m5IA; Tue, 11 Oct 2022 22:06:10 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: Stefano Stabellini , =?utf-8?q?Daniel_P=2E_Berra?= =?utf-8?q?ng=C3=A9?= , "Dr. David Alan Gilbert" , Jason Wang , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Greg Kurz , Eric Blake , Laurent Vivier , Stefan Weil , Thomas Huth , Samuel Thibault , Markus Armbruster , Paul Durrant , David Gibson , xen-devel@lists.xenproject.org Subject: [PATCH v11 17/17] net: stream: add QAPI events to report connection state Date: Tue, 11 Oct 2022 22:05:39 +0200 Message-Id: <20221011200539.1486809-18-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221011200539.1486809-1-lvivier@redhat.com> References: <20221011200539.1486809-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:ukB643UynxESkuvexvwLMO3uLV40x/y239Rykp2Y8sCiFWsyJzz 351vqoEiEJ+zfGSWXiI8XZ0XxoDl75/BoX8hEZBsBrZQRf7ry6FHk62R2I9B7JdBl8SOFqV G9iftbojj91MV499/58NxR26Ka9FYnfrnqkyhvFfI6Dbl89+juAGFqb1WNwMcQjsJ1JiA4F 4xVtj1/D/e2gkxRQkwCAg== X-UI-Out-Filterresults: notjunk:1;V03:K0:aw+E7ZncHHc=:sGiI6m52tLA4EWvJQWVP1v wqQwOtOSmF+ipRzx0rMfFy78aiXhu++rHuFct7/hixs5OutDiOy2cFQAs23H3LMEZrV+Fj+w2 Jxum8wTo2mnQOH9V63eme0Vk9ldwizckHyFbYzhmN5o0TlkCarhyKt4JuNi9NUkLDSyCBIZbX Exm3/VS7xtcUFMGtrBCWdo/LSwVf31G6ViTPzv1F1tCMlDyNKwGN86ZEsMBCyYANIJMNEkiN7 F5shUVmMlTWl98xQoJyPNCSaezFhoWi5zua8k4ZOGXjDFpFjkDVkSPs3pakeq+qjK9YliM1eL 0yUApUMAiU8uYcUJm0y2H+9Y3NsuJzKVo0mrgB2CDpA4cb5zsPmWTGNJO7oW4is3iYpCcv2uA x420htJSvn727nVtYfz12NUDtqJnYngX4WW68CT9RxuuFSPMdfWYLp1QFzTCvpIOeLlEuLS69 zM7joIFwsjKL3Ws/t9Rk8xsi99GgGNFGhjJbJP3f3ioXi/Co/MLcg0dlQtXv3146ZyY7F4b+n MSr0CvZz4LUx0230ZXxoN98l81Af4ai3jQujngFai9+pMcXdBwCqmOCy+F6kirkyPjCKFvWDU N7laJXqxe5RDMfeMiJHGm3+Q2i4VJ/AfVSm1k7LqTxv2HRcDBtV9ZqF7aF0dCcW0VaZLHnRh/ N8qvPBPHUzZVcGeDmjk/MPxCtKKuRMerXVo/GNlcVDuGf8bop8WWZpBuo/kS44bWnOr/E+M1m +Rq6Tt4F8wSaFL8PgNCx3mhYlPX2B4zgZtVYHkKdHksYw6B7vZlNND8Un8x1uzYt9v8F5Kwdw ZM9HMrG Received-SPF: permerror client-ip=212.227.126.130; envelope-from=lvivier@redhat.com; helo=mout.kundenserver.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_FAIL=0.001, SPF_HELO_NONE=0.001 autolearn=no 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" The netdev reports NETDEV_STREAM_CONNECTED event when the backend is connected, and NETDEV_STREAM_EOC when it is disconnected. The NETDEV_STREAM_CONNECTED event includes the URI of the destination address. Signed-off-by: Laurent Vivier Acked-by: Michael S. Tsirkin --- net/stream.c | 11 +++++++++-- qapi/net.json | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/net/stream.c b/net/stream.c index 0293e38e5b57..821ae3265356 100644 --- a/net/stream.c +++ b/net/stream.c @@ -38,6 +38,7 @@ #include "io/channel.h" #include "io/channel-socket.h" #include "io/net-listener.h" +#include "qapi/qapi-events-net.h" typedef struct NetStreamState { NetClientState nc; @@ -168,6 +169,8 @@ static gboolean net_stream_send(QIOChannel *ioc, s->nc.link_down = true; qemu_set_info_str(&s->nc, ""); + qapi_event_send_netdev_stream_eoc(s->nc.name); + return G_SOURCE_REMOVE; } buf = buf1; @@ -243,9 +246,10 @@ static void net_stream_listen(QIONetListener *listener, g_assert(addr != NULL); uri = socket_uri(addr); qemu_set_info_str(&s->nc, uri); - g_free(uri); qapi_free_SocketAddress(addr); + qapi_event_send_netdev_stream_connected(s->nc.name, uri); + g_free(uri); } static void net_stream_server_listening(QIOTask *task, gpointer opaque) @@ -317,12 +321,12 @@ static void net_stream_client_connected(QIOTask *task, gpointer opaque) g_assert(addr != NULL); uri = socket_uri(addr); qemu_set_info_str(&s->nc, uri); - g_free(uri); ret = qemu_socket_try_set_nonblock(sioc->fd); if (addr->type == SOCKET_ADDRESS_TYPE_FD && ret < 0) { qemu_set_info_str(&s->nc, "can't use file descriptor %s (errno %d)", addr->u.fd.str, -ret); + g_free(uri); qapi_free_SocketAddress(addr); goto error; } @@ -338,6 +342,9 @@ static void net_stream_client_connected(QIOTask *task, gpointer opaque) s, NULL); s->nc.link_down = false; + qapi_event_send_netdev_stream_connected(s->nc.name, uri); + g_free(uri); + return; error: object_unref(OBJECT(s->ioc)); diff --git a/qapi/net.json b/qapi/net.json index 6a1a49749294..69f83bceff3f 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -895,3 +895,49 @@ ## { 'event': 'FAILOVER_NEGOTIATED', 'data': {'device-id': 'str'} } + +## +# @NETDEV_STREAM_CONNECTED: +# +# Emitted when the netdev stream backend is connected +# +# @netdev-id: QEMU netdev id that is connected +# @uri: The Uniform Resource Identifier identifying the destination address +# +# Since: 7.2 +# +# Example: +# +# <- { 'event': 'NETDEV_STREAM_CONNECTED', +# 'data': {'uri': 'tcp:::1:1234', 'netdev-id': 'netdev0'}, +# 'timestamp': {'seconds': 1663330564, 'microseconds': 804317} } +# +# or +# +# <- { 'event': 'NETDEV_STREAM_CONNECTED', +# 'data': {'uri': ''unix:/tmp/qemu0', 'netdev-id': 'netdev0'}, +# 'timestamp': {'seconds': 1663330564, 'microseconds': 804317} } +# +## +{ 'event': 'NETDEV_STREAM_CONNECTED', + 'data': { 'netdev-id': 'str', + 'uri': 'str' } } + +## +# @NETDEV_STREAM_EOC: +# +# Emitted when the netdev stream backend is disconnected +# +# @netdev-id: QEMU netdev id that is disconnected +# +# Since: 7.2 +# +# Example: +# +# <- { 'event': 'NETDEV_STREAM_EOC', +# 'data': {'netdev-id': 'netdev0'}, +# 'timestamp': {'seconds': 1663330937, 'microseconds': 526695} } +# +## +{ 'event': 'NETDEV_STREAM_EOC', + 'data': { 'netdev-id': 'str' } }