From patchwork Thu Oct 20 09:16:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012890 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 6DFB8C43217 for ; Thu, 20 Oct 2022 09:25:29 +0000 (UTC) Received: from localhost ([::1]:37508 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRns-0002K1-Ex for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:25:28 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRmd-0007aN-99 for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:24:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50480) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfX-0002Wp-7v for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:51 -0400 Received: from mout.kundenserver.de ([212.227.126.187]:48161) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfV-0005Hh-6P for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:50 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MOiLv-1oT5Qu2ev1-00QETJ; Thu, 20 Oct 2022 11:16:31 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster , Stefano Brivio Subject: [PATCH v12 01/17] net: introduce convert_host_port() Date: Thu, 20 Oct 2022 11:16:08 +0200 Message-Id: <20221020091624.48368-2-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:w7b7ew+XCKzAiNz98MdvY/X+FRrIVaZcwXchn++di0t+4lHR55J QMUTAMRUkKzYEwok+QgfhDJNqEEZFDulUNjrXxYNWfK6dhMZaXtVXn8IrjBYdv1ujSbM52j 8y2Ai8TzcqOd0yhC7jtN8I9Wwnxisu7t1ChvZ2ICyw1NFZfyYUnsx4vUaLfvRB5CR+5oB/+ LvXVkNO2l1KSYUHApLoZQ== X-UI-Out-Filterresults: notjunk:1;V03:K0:hI15SSxCSiM=:I8hQqXJjf5XOelF9j214RG fXWFmJFM1zApl2umJyJou/JcG+4y+DKl6/dhnTgstHZfa0u598fi/tmGz/HzM6IANRALMc/eD 6DwrM/xYp6UE/V2s38VeBrwb4dRW02QtlI3SbDIsMDo3U16SKdb7hmf0Z4F8e/xB/8STU7oAJ I/lz69i0JqHCjVt/wn3VwRDi/jxrz8yUumJj2iLZuKHfuLnIIAJwwF7NXSlntEhDmEm67yQ9P fRd8XrQ6cXjtouTXYZMBd8Coq7NCE8+bDJrtQSDEhdvHFeUQIlFYjSf3NrI0b7Z/UNOhtT7tZ hSNtv+4B66mcay5UGp9m3FbAAKK1Iw9+Xe0DMSRq9frr7zwBKCzLydXSy/IPc5z3ZDIO0pBZe s56fPDgeV/6PScq2ckvDlThV0F2K6y/GaQu7b8lJbiz9CDT9tVGIOOD/5g2UidNsbjxS4aYDP 1IkzhGnpNXVPXNz1xjbqDfITTW1Fm83c9uLBYehEx8yM32D+JIMuk71/mtDORpK2mbcuFtZg/ 5lkHhN/vNJ68fzjUQxQHB6rVnCNXANvZ4yHdhXDj1rPfje+/pl/xLNUfppwhOIprymMZ4SEFB Ny0kwx+JA8tAnvNSlrQk7WkKYWM5Hrzklq6tHrqhS3DIKgzhub5NZwBW54ktbXeln71Rlfoxe HRe3hTvFluCAZ1eJG4SS679Z4PDWGiIaimjt1u1p2f7WvQCFoJY9iTk74T/yQLVBB8eTPiYqd G1v/jNDzJkllo8H7QdZmna98mHX6pps0xqoXvNt2LDhvviGJDhK7jDi24h6Lppoot0GrRYZAa Wsa5tWw Received-SPF: permerror client-ip=212.227.126.187; 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 Thu Oct 20 09:16:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012889 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 1B344C4332F for ; Thu, 20 Oct 2022 09:25:24 +0000 (UTC) Received: from localhost ([::1]:36678 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRnm-00025b-Vo for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:25:23 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRmB-0007J9-UN for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:23:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50476) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfV-0002Rm-E9 for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:49 -0400 Received: from mout.kundenserver.de ([212.227.126.187]:56539) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfS-0005Ho-OX for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:49 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N2m7Q-1pFObn05SG-0137ju; Thu, 20 Oct 2022 11:16:35 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster Subject: [PATCH v12 02/17] net: remove the @errp argument of net_client_inits() Date: Thu, 20 Oct 2022 11:16:09 +0200 Message-Id: <20221020091624.48368-3-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:GcI+SCNvkXqQLfBRQLhwGtXM3muJ7p0E+3r6yO9gVQ4zkONOeJ5 r1rQyZXlUOg8IvOZqlTK2WrBGx9rl2Q5ngt3dEtTLfspvpad4W8KLrX6Gb/CXXAv3T3OYgw 0rmwD7ybGZSopSkeHbwY1jVRN+erL7U14XNuby8q7WWa3MFUYGfyYpz7yLOMEFRXi+lm5hV KEeOsNHiJafL1Tuxh+jbg== X-UI-Out-Filterresults: notjunk:1;V03:K0:HAC/78TLA1A=:1olf2L/xfqbx0inlXtevxY e0xuehDV1mOPVSJAzg0nb7C2svioJ/o1T8xEQ7LTD3wZGn9KdUavzr1BLg4i488hjdSG2l/kA SITd2V8g7SbW4QZkHLedsmSP2HwP7ewcO5bpw+nEQEVFJEcnO64qo43+d9SeXh/7lF6USnGuY Ctsh+Pgcpp5kLJ6LeY227sd1obkkoX6TQa4p+lzgiTmVQ+EmEsFW/fuRzlZeb+sTja7lMNxAD q55ZqYWgLuYHI8HSWwAc0A+8KladR13D2nwn5QfQ53TqqZ5MUtefuaXHPPIGP8GqnFqNX2SNG ZtKYKGIu3OWMdxP/wr3jVGwLxmBadDXmvyxFSRxSZg+UwWLV6aRB5+LYV4r3rAeSr4jDkp9lm GIyrZPVbsQc9QWdrPCn+RPM3BFYhCFqwhj+xcS+trKEdUBZLTYVgIwqpN2cw5+8pjpQrDlIeC 5+ag9hkUY2/JHHAngwxHDTjKUFGI/xZWIJc6uMmehEmPVIu8R/YZGZ7pgGeOojJLxU+ICxMQ1 RRTQ+ivJQM77YDE/Gz48uMXkCPt3fsWjqnHpi7jmGx9DJzHH+iXyg1a5nr41k8F6iy6KXINdn EWnzHS1SOscKLN2l0iCc++/+W8rXF4fG7NkxkXDc7oayMTw1BsA0/5L9L5MzGl6HR7PVx13zS 5/E+BjYVjC1VVGZDA5z4w7BUXqrNRmBnmU9n0d+GN3/wq6G36bqefHACV1gjIqwsuklGcHbvj QFJ7AUvZTOxSNGmyg2LjGZKMXdSBUJ5mpqR0dDb8Pny0IOvWk7wUcUETbC4n8RzdK4LdqVExV I5EwEj0 Received-SPF: permerror client-ip=212.227.126.187; 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 Thu Oct 20 09:16:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012938 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 C7E74C433FE for ; Thu, 20 Oct 2022 09:52:42 +0000 (UTC) Received: from localhost ([::1]:41004 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olSED-0003SM-Jv for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:52:41 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRpb-0001x4-Uy for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:27:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50484) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfY-0002ZC-6S for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:52 -0400 Received: from mout.kundenserver.de ([212.227.126.133]:54509) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfT-0005Hs-K1 for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:50 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N63NQ-1p9sIG1hkm-016OzW; Thu, 20 Oct 2022 11:16:36 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster Subject: [PATCH v12 03/17] net: simplify net_client_parse() error management Date: Thu, 20 Oct 2022 11:16:10 +0200 Message-Id: <20221020091624.48368-4-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:4+NFKSFp2Hij0apaps/Q2/rgGc65iwBfvVhBoGdLBuqqtEwusC+ q0jNyFjcVAi6iQic8jBMtjYjKLmz/ULbh4oSvJeTiOjSOPkOvQs0quJnczPXxei7Wdqez3v vhd/NixhpoJaSNFv80dHO+BZ9caakqorWtZoUeW8+Pu3rOHyy9fvr0XtdAbu9koYTcxPavE hcqc0pXAUecXdcxTKPVQA== X-UI-Out-Filterresults: notjunk:1;V03:K0:iiuq1lxlvJU=:nysntMu7Wj00UYdxw8Xhpt MaPLgD3i/jHiAlOnBA9XhZTAg7pcQHrPaQZuUcEafIdg4x8FkefKXLSelNP843i0tWC//x5nb R6IBUVMany+OkZfHAJXHQXyB4YuYen+1Ejg674gPuCyZF8zIKv26OUpWBdEU2/cSfNsKNE0tr Q4LV8XQ/Im1zQ0v9DcCVtTAoJRL8LHt8Ebx8NZPSUpNZNdAYOPQ3efdaxGiPuxcDqRTA0EhJO XAJ9g8NCsaMqB3Skj1LM7Z+ig7TNnhaFWJo+fs6DrTLOJM7VpGH+T9AE/ErMV8XO1SEjj0iIF CiXCcyeor1rzKlPpwg3QHhHUbWXGCyY/1COahsWzuhU+c36pz0QDmvzjsPxGI3p0t5dzyJB1z ejjKQgIaM1BgCwqQxs09VMuSRwmw4vHcYrM9L1/DHGCyQZYNZ3JmkM9/ZrH2v2rNcdqLDwBEf hCYDHhCzuCOAu+D2cOq9/Ryb3rnEEoh+C2vS9nIvSfcSR1nhu6FdJTsU3XHYBAMxXlh61b6be 2KO+6e6fis5TFDZxZnn1C6R5iCdKqzbg4LjQGfmQdfp3T/zOheyeQ0nMWwtl1K0rYipFjmaT2 3IutMyfT+EYO/Kma3dgdawzSx6Jss9d/DsNM5W3CuK9HBlhAKp/j+Geoew4AJfWfTKqKDfqhn sSzFY4dduGQ3FS90VXfs6sMhJ6eJOXDG4TK8Gz7Vs8mbCZSf9zfgWKgwcrpbHGBQxGrG6bZqx Ypl4DUX3FUTAxRaBJFOTQI1UWnfmjaayIXJ/I+QWvZOQN6rFRYE97R/iZvMGYul8jS6yd4B4L +OPbakG 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 Thu Oct 20 09:16:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012930 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 D7BE3C4332F for ; Thu, 20 Oct 2022 09:51:00 +0000 (UTC) Received: from localhost ([::1]:36002 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olSCZ-0002Pj-Df for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:50:59 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRmb-0007cn-UY for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:24:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50482) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfY-0002ZA-6F for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:52 -0400 Received: from mout.kundenserver.de ([212.227.126.133]:53483) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfT-0005Hw-Si for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:50 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MPooN-1oPm2o3WKJ-00Mw9d; Thu, 20 Oct 2022 11:16:38 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster Subject: [PATCH v12 04/17] qapi: net: introduce a way to bypass qemu_opts_parse_noisily() Date: Thu, 20 Oct 2022 11:16:11 +0200 Message-Id: <20221020091624.48368-5-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:ReGa2xijlRqc2uB5K/A/Uavq/2LeduhZKqLIZdwlr5WDSUDMT8E M7kkMAWNTPH29ZOPof6Of4gPtsPQiNbeVq0PgrS+Mp7Szi5IZYc6pIfJD9FQBYKgWG8pNom nOw11/vHu0AKSGmq0igDBpivm/N23GYmIsjOH/BY3H5FAtHfHs/PoUEWBfbpXuJ1ICDEcKO wOTjk7on2atP/sUEgHkjA== X-UI-Out-Filterresults: notjunk:1;V03:K0:1KUFuBRpX+I=:my5srp0lfH4xD6RfMTAHVZ Cw0KTwYg9XZzuH3RRY/UzR1gSc8TZnHIl0KZsce3OKxse4CpRnlO2g1fQw+wcCmyMqcmkCyC8 zv1pakwvBJLq6PDpSz1Qkp/blW0NGHnvfDe/Zce80GO+1AAdkEOjBLenbSY4OVgQNCk2Yfh2c Bv0umuZ1Ac9VOk3bo3iJdM4+yt2h8PyeidKtpYboLV1vbJjYLEwmQlNBg0jRZDdIyo4v0mARq vuFIjhIkVWRY5hC5g7uXg7kQ/+3c7fmcCx2ZDB15NOuE69u6NuXA4d12pmBdDu77L3byG2Jhr HlHhykOITozQi4RNwIYPCnvdUzeRN4dN1TAXAzZtS7cC9ff2ZIRlEZbqKug8UtnFk27meTQtd CnhkBG7xIYu5ehV6qw/KWJymUjxpnfR7Lknrs+gzh93224b05ZnvwqxPlg4e/t2v4k/TixeQF sQYatf0qZAdQJ+T9jLtNu7uD9jiBsehF/aW4IxM6nOcuZc5Lfe9aSC5S7nHJRW7q1/Vdj6FXm DdtlPdZqjwd2SE5BVXf5NhqSBCaf4P6k30gIO/y4o9dxKXuxwdKHD65GjBLuanD4Jw8LSXWpn 5+mFZaPc5dw/S0aoM4wTuD2wyu/ocvFI5BfR0YwmLgNkMyQbnKKvUIlZZATRS4VDxEELO54Mg 8qVp9ZOk6Njm4ISnu+l7AJlnot8nDp2FGNFUVqsgWJVAXMpV3bqT34CtNvDirI9X2R5kgLqCW TKjiBYvzxtpaqLBWeOHd1/DsxQl67o4G3YCPuYoPhhNe5t4VEph7CXBfOHS1kf6Qu1bIouCvC Dz4xvxJ 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" 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 Thu Oct 20 09:16:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012923 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 82AEEC433FE for ; Thu, 20 Oct 2022 09:44:20 +0000 (UTC) Received: from localhost ([::1]:60776 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olS67-0003Wx-EA for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:44:19 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRnJ-0007yz-EV for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:24:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50486) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfa-0002i2-Cd for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:54 -0400 Received: from mout.kundenserver.de ([212.227.126.131]:53225) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfX-0005IG-T8 for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:54 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1Myb8P-1p1rx417W9-00z0zb; Thu, 20 Oct 2022 11:16:39 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster Subject: [PATCH v12 05/17] net: introduce qemu_set_info_str() function Date: Thu, 20 Oct 2022 11:16:12 +0200 Message-Id: <20221020091624.48368-6-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:8I4TyENrrMKhmWwU+2x3ZsBFvFVnDUx5kFcoBW8l6/FpkUNSskF yvW+l7dFaRqabKnXOcyaqcJyPAQYQ4tT1JbqEiTn6mHp+sdoebkGhdh00oWZnzvdJ7S/I3t dOZi1Y4L9hpjtXI4U5uldvXfvZgYQbf8fKs9GkTO/NWj46k3rKKdD51p4HDBz49gGNc5iJt /GPhQH2Zo7MX2/pyD5spw== X-UI-Out-Filterresults: notjunk:1;V03:K0:iiOSHgZ6csE=:l2HRe8vQ7ARtTNu0gD8GWG QqFgYnVGB8VlmrpRbIeWGujrx0PSQ+DWNyNZ4W957RK5vhd31m/eizIrFY3nBCOL4rFzt/MJW DHP4TfD95FRj+Jn6uYG2lz0o2S70lwp6VrKq3ht3LSMIgwiVZZchT3D/pqWXZQG2kUsz3b9Yu iZgRPqaka+41DFoJrNkfX2IlZ7kqdYULP+7vFCOz88ahrMxSWcGPqkitjen+ylobzUHMZQiaF jkSZFVjbYXKoSoQ1lc4j7+2mZHc5yHFTYz/vSGY+h95l/OWdZbLmpXRqyXpEoWfhE9pEaae5W 8b4jDitWhL+E4MaiRRTGmfOtLpSqIHUeiFHvq9hVkLBbLVMbAYcX4fJS3fcLd6hsD4vwP8yeW 2nvPH6tSwD9SFhpeKDHWhBAOEhE8n2vZTf/5KKzudvmow5ElZy0ScZ1ERGhTZPmarEk4kIEJ2 VLrpBmc7gLJrFvTZIQQdzPMIV6beC8XIDoEmrE0uoo9LuKGziKmdl9c82vox+OPklzan1AKJN eUCePpUOVON6Z5s9NqjCtWO9ieyTNhFdNkSWpDeZBQuJ7COyi3NQpNsq3CZp3e5qa9Vm3cGC1 j/Amf0j0a6GOaA2H393NeD2eBVXV5jhRWdj4fmaf1vLK023fQQxXk2hUQO666dLNAesPNzfyW Iyc5AA9e5hxLfubrl6NvBqmPF7LdRNLEPP/EiyET8XQ8XA3czBjjKxEMiTIDfKBZ1UyNmIDmH BwuOAfyVeOEKmpDBo2e3TyYhvyyacPH2/r3kRZm42UFaDApgDV4UGooujCZmtka8gV7wJvAMo IhaVqp6 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" Embed the setting of info_str in a function. Signed-off-by: Laurent Vivier Reviewed-by: David Gibson Acked-by: Michael S. Tsirkin Reviewed-by: Philippe Mathieu-Daudé --- 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 Thu Oct 20 09:16:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012916 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 059B5C4332F for ; Thu, 20 Oct 2022 09:37:45 +0000 (UTC) Received: from localhost ([::1]:48644 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRzk-0000Os-0J for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:37:44 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRnK-00087Q-GE for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:24:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57116) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfb-0002ky-SP for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:56 -0400 Received: from mout.kundenserver.de ([212.227.126.131]:53847) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfX-0005IR-Tr for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:55 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N9MlI-1p8lpc3msu-015Jb0; Thu, 20 Oct 2022 11:16:41 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster , Stefano Brivio Subject: [PATCH v12 06/17] qapi: net: add stream and dgram netdevs Date: Thu, 20 Oct 2022 11:16:13 +0200 Message-Id: <20221020091624.48368-7-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:3gfEwflVA1lEv+XnWvGUk1riWyfwSt6fpgqwotuUZfhi9Lwk/D4 wVmBmFVRTekUQXTNhqSjhjlgPMD2a+J+87ZEiZ1yJk/rxuQsXSGUoyHTWrhFQ1p1YO2FunH o8HzYsME1kTE7heyJJmMHNV+jbzYuSmELXqjJySenpsaFi2i4DbJLIp6kHmu9QI8jcCQCXd zEzyAJJ9T0XE2/cL9H/Sw== X-UI-Out-Filterresults: notjunk:1;V03:K0:42QV295H8ak=:WuekmcAzd6q4H4/XgEVZQW m8FlFZqmrNu38jEVx13cQ6yUN5Aw0Jp3zA1TgHUmP9bjM7uojbE7ZcyYt4pfj/H8/9of24jTQ 6jOp0rHZplI3eck/XRbGVH9qav7hg+aveLY9t+3MAYeDttrbyoMRzb6Lq8Cek18Hv4BqLxsTf 2Whf7y17ByHMKDUBFzIz+K2vHB4VCXh1Q8VmYMDnt9Pl60HkfmcLV6uC31JRqVoT6rPYmrtle YTnIYtynGalws3tXoLYSLn+LvZ4GboK9LHHy8GIUQ8uyaYkhe8M9loCxqQw+nAYavTNYWLWhH xAMXE3IPj6B/TV5GKBJq+VVOsRilu8mTSQwSU8EaC3tU7mYPTI40tzzhvMInU6/xI4CvZO+j0 yTMBm+J8vfNWBA6E4KKBX4MCqRlDrZNla0X6B98HQHt2tbcOfDzeLFObxKQmXUfEFFDWfiv6Z 9RRzEhEyHAyNuzpyEUUHPRwSvzA7QSaKtA8+ZICz6X+5YEhLPf3oU2mMsxbT0wrX/meQERVeY IiejnI7I6AjRH/YzpN7Rm5rr41Kq2MNQEeRoe5VzAdPnZPZp6xSh/HAkMJVGDs/TDmZCASdLP 4/NOfDB49AXFx+wBTnimm5yMbv2dMULmNXYGdRFstfA0SFX1utbENY9PYtdYDF0rMESv3Jk0a ViW2yItKuHJ/LbZ2k9fTErneRdaaSErmZGhPFYo9SAGw+gZvA2rD3ALXWZRYIFrzqunOyAeAu oMZRZ8rWgg6FA8FleWWVHiU93YAxqDuaETQR4OnliIAKmGt2NmtCWzo9xqrxdzolk9AulF5vc qpMA6Ae 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" 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 (off 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 12b6d4e2dcac..673e39a69797 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..0a7e84749a3f --- /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_client_init(peer, "stream", name, sock->addr, errp); + } + return net_stream_server_init(peer, "stream", name, sock->addr, errp); +} diff --git a/qapi/net.json b/qapi/net.json index dd088c09c509..185748cc6c6c 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: false) +# +# 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 eb38e5dc40bc..396c1d11e1e2 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2772,6 +2772,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 Thu Oct 20 09:16:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012941 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 703E9C4332F for ; Thu, 20 Oct 2022 10:01:10 +0000 (UTC) Received: from localhost ([::1]:43978 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olSMO-000477-15 for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 06:01:09 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRmy-0007my-BH for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:24:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57114) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfb-0002kx-RC for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:56 -0400 Received: from mout.kundenserver.de ([212.227.126.187]:53927) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfZ-0005IX-4T for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:55 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1Mqrs9-1pOv8d47e5-00mok3; Thu, 20 Oct 2022 11:16:43 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster , Stefano Brivio Subject: [PATCH v12 07/17] net: socket: Don't ignore EINVAL on netdev socket connection Date: Thu, 20 Oct 2022 11:16:14 +0200 Message-Id: <20221020091624.48368-8-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:pTG9mgQH3OneQJT9lW8xR+6jyWFloNcXokaNuuau/BeQMn6894i QvLR9uWEG6mcjv8jh1WeG1Wk8Uk05xDnFHRgtDphQALVaQ4GEIer3NLtBRjIsQ5v8BP9UZm 6EIngEz80lfi3mRLNnzz6kcZD2jMQzS2Q7SKlOTxy0woczVUAJRrDtix8t6TJ7UnvYuW7bP WlH7sRJV8IwOy+5xFCtUg== X-UI-Out-Filterresults: notjunk:1;V03:K0:QgXbyh6xtH0=:cEThxxYGl8M0XF54eH8+EJ 1bz8h1K66qwNDz3xfDjEBZ0Q+FQoTUiFO4lcNsMNjTXuwyt9s/qAT7gyekUfyoNx2tAUMFEBf E5OMrbzY5poJCPUxshsWAzZKXaHzZ33Q5LWyrgziInxZp6fiDWra2nn+rDNJlfvW88oKjlqqN jUsF4k+xdpN26WVqsYBOAcyA5VFCv54jiW4M8vyDS+KE9Cg0bbndTXMbBR0QyezAhJ+jDp+dG Y6YEjUdMI6RCjh8Xf/Nx/+onlTQpAkFqDRLoS816DA3CacEHCzJmkIjd1u10f9CKFiHXPo8ge 2h0CA+gSTL7A602YNk0f+X+A196U3kwK8RMuKFNVf0Gpj+QBMtaDoUKIEBpOAO43yZqVtZV87 +T6w+wFOj/1EEs9dKugz1bpR6Geu20UtbRHOIxAsi4eRe0T4xseJ36tsn9Bj5usIJFbGd5Lgy jwtf1mAF+YdIV+eXEpGUtOuuGN35tvYaerZtRjgJ0VwucCHTcAJqH1W88M7bMUCNfrmg99HVV hXY6tszD5cHSb24h6qxkdHGZ7aPz/wV4QpfSgJwzKQG3mdKHhz1OrV8EgDaMMUlrKdvhx3c7O IVrxOhKo10TtzYxWzmWvfZmrZoUTjgStAi+BaCjPZUOihqeYaRlwm8BuPh60Zfz0FwIUrvXBy nMhIzdj8Ohjn+mwJj+rHu7jyG23Z1u3k7kIUuqIEFQAKIExePShcAwyvu8ioczMK2RF8x6Ug1 O43q3X7za6ZBoLqAqtPzkcdSdly+o1XEdfLBw1FFe1Z4PzuA9B5pAXgAjyc3jPwXvmWwILCPr q59iu+2 Received-SPF: permerror client-ip=212.227.126.187; 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 Thu Oct 20 09:16:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012915 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 C0E02C4332F for ; Thu, 20 Oct 2022 09:37:03 +0000 (UTC) Received: from localhost ([::1]:44158 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRz4-0007Uv-Ce for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:37:02 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRnF-0007xF-TU for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:24:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57118) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfd-0002qG-Kt for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:57 -0400 Received: from mout.kundenserver.de ([212.227.126.187]:35259) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfb-0005JL-Qw for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:57 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N9MlI-1p8lpY1kgO-015Jb0; Thu, 20 Oct 2022 11:16:44 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster , Stefano Brivio Subject: [PATCH v12 08/17] net: stream: Don't ignore EINVAL on netdev socket connection Date: Thu, 20 Oct 2022 11:16:15 +0200 Message-Id: <20221020091624.48368-9-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:rAowcpovUx7VZ1182aMugTyHfqst2uG2cFQ5qzJT9yB3oYFUnAT CWbhDc5VvbyU5SN1HObxq+zbVD4kHfvYytcZMATeukaALOIRJRZaYr21CzchiTbx3J7xQOQ GMcBCVfpQ3YpaQPlGDRscahcM+ldA5VmZkGtGINwDglcPDB3B/zFjw21+xDj0iIRm+KRQWh R+l90FLVGfvfvnaoJPMKg== X-UI-Out-Filterresults: notjunk:1;V03:K0:T32DJ/xxkVY=:EQMZ+yfhGZk2VN7S22yqgh nYCFS4LjhklSHZIim+p2fv0N/Cef/OvIhT+WkH/5jZhaLuzibvnaEtGLu+G7KqG1lv4KgHmcm aB66i5zFLXB1KrrjOHGui2d4nfFtvZjLKwyschy8Wdn3MZ2XsJ4fBAYDqzIuPjNTRBv2zjoue pYiZITLtjEFv09gjZXTr5FzcFUtTzB3vDPIsX87EN5pKhYX2gAU42j44LO8Bc9g17oc/QAMhm RlgLbKocTfpXWNpqA4A53C73YWU9nR+ce7Cqcm9nXqY2+15N6z5YNTvo610hvnHQZXDsxkMTH MzeYBuqqR1wgz/2WhSk1CJavDQCnXe0iz7n7agjh4lUAebK7HFIFW1f/U5nsM/uBklzP9GDrE VVE7MrKvr+eyEUNytrdr0QEdmg63NLodzw7nmkkVqT4cmr3z4a8z6zCG22kw1Lp8Csy1p4pXR rV4sEcFv3JamjxjFIS/Q2y1x45rpCX3l/ncXeBjbfLrUjv6I7jZ2sopfvaY2tt4MIRadsdPDr nN4ecJ3nYydXKIFtS/0S8wQI6zquVo83soydFxJMa1xeB9Iv/C9ftSgtMbkJ3szeG3uY6fv2y wh4Ttmh1m9gD/gAGOgHkXCjZoieKuz8VCxq+LM2U5Sfv+nJjjL2kPXgUc3HNNLbrh99poXfWN J+ufOq6BSTgJA4P9vnwDKZEwKxBWS6UUbwM/Hb/MaawrZpLTCSIgEl3sNT+S8pfGxEAyfTTCl xpKLCEiGMjQq5Zs7MDRUI2+QWhG2Q0T92yP0bybsQjbONI48zu6BxStrBsI9QUQK6zocntv9u tOWM3pO Received-SPF: permerror client-ip=212.227.126.187; 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 0a7e84749a3f..e4388fe7e45c 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 Thu Oct 20 09:16:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012908 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 F1087C4332F for ; Thu, 20 Oct 2022 09:33:53 +0000 (UTC) Received: from localhost ([::1]:51176 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRvz-0004Q6-Ou for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:33:52 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRvy-00014L-Gz for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:33:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57120) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfe-0002vf-N4 for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:02 -0400 Received: from mout.kundenserver.de ([212.227.126.187]:50101) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfc-0005JP-Im for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:58 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N0o3Z-1ozf1k3Xl7-00wp8V; Thu, 20 Oct 2022 11:16:46 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster , Stefano Brivio Subject: [PATCH v12 09/17] net: stream: add unix socket Date: Thu, 20 Oct 2022 11:16:16 +0200 Message-Id: <20221020091624.48368-10-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:gMIOYLn4bRLZVNt9njFFbtrAEzYsUgReS5jZtFBk3pdSs0LxHQy GxLfEWKviqDF0IjIAQ/jrRb2ICNe6YyF7dQhM1g0GUS5Qy0LhGb4D3WCTn9aNGfksWGXNEo zTcxlLvchngiUk5tZ1/m2JI0V4jNpS6I7x0t7S1erXUfzR3QUlaYO0sjYsbxmt19qTPKrVv fTp9GzleFMdTnKYUfLfsg== X-UI-Out-Filterresults: notjunk:1;V03:K0:SJ7Fk6DGnrU=:m6cl7BzvSmC9W8OEnE6JAF Vb863dIXekgXMiBUv2Hunr3HhpV13W/TOdE+sk2bErK2wiBYmhn9p8ISxSo2yAO4OLdzlJdqk 6bvCdO//phaTZer3PbRW4J5N+b++nJkrj1AMstGk6mwfVrQNXB/07V1WkaILSyhtLHIzkddv+ KMsQI1OUMXGQF7Al+JewxbFrW70hxe8wf3p1QWM/sTPba+Ndx94E5WobIuT+Plk92GCX7mir+ Pokdea0+SgBS6K4J1mLFwRxIcCrMqje+kDULR5Lxga3myTgu1YY3+Kjm+QloACqvwoO95d1vz 9F+wo27f+/LkxZfrwvMGHH64qa6GXi3PCTo17j+cXSbE4oarz+XTERYKrDUHDDZdtrohFXBCR PrsYn1DvWuON8iZJX0WhkPDk/nc58z58kZhAiLQoGSc62eudGRyvUStQWQJRQS0U4sgca4LP8 SJTTRrvDy40YshUeGv7rDad05/BfyRJws5Rp4sor3z3I//lf+ilyevlJ3k/QQGL/A3SvIA9ZH iz5i8gCxly4qiiK0PgAHrQuLF+6ucU2bsyOhtQ8/akylWPekeiyGKwpzg3D/cFeFxK3X/GbC0 wvPfSqowSLqhhMZz23LFvg5fMChrjkzec2BtY5DVMHtQBQ66aZCux0CJI0dAU9/ZHQNgR7fz7 DfYtOL61sRokCyaRKK4rWHjY8RnxVyDIQ3GW0TFjtQrIx3huzIe2x/VUppTyJGs2SqxcBTzud l2aT1w1CX/pNJpXhr3lt8uHX3MYV7yEhPWo4o75ZCtImmOk4W+BEG6vcfv4LbBlkDOLjcxsOR DK6rCx8 Received-SPF: permerror client-ip=212.227.126.187; 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 QAPI schema Acked-by: Markus Armbruster Reviewed-by: Philippe Mathieu-Daudé --- 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 e4388fe7e45c..884f473018da 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 185748cc6c6c..aed4ce1a97ff 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -583,7 +583,7 @@ # or connect to (server=false) # @server: create server socket (default: false) # -# 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 396c1d11e1e2..98e2595df93b 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2773,6 +2773,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 Thu Oct 20 09:16:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012922 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 41CB2C4332F for ; Thu, 20 Oct 2022 09:44:09 +0000 (UTC) Received: from localhost ([::1]:54476 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olS5w-0003CI-5w for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:44:08 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRnJ-0007zG-7f for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:24:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57122) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRff-0002vh-BQ for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:02 -0400 Received: from mout.kundenserver.de ([212.227.126.131]:57583) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfd-0005Jb-3m for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:16:59 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MStKw-1ogc5J1W3y-00ULDc; Thu, 20 Oct 2022 11:16:47 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster , Stefano Brivio Subject: [PATCH v12 10/17] net: dgram: make dgram_dst generic Date: Thu, 20 Oct 2022 11:16:17 +0200 Message-Id: <20221020091624.48368-11-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:stb7ru/sJjlHnVoJzWhmbHovPaYhdqFTUyFBfLup1gkHLTVIxiz hKI1Ex2fx4faPA/kbjPEbZyEpBxysCm4udvHyjCbx7FlI15XqLI2f4kZ5+X9qYVmYvwhoGB u5jFzzQa4BRgePswOA2PCnMMCtvOzLccCoLZEMLUrDctYLN4qu5w2EaqPrpbtwOChp9+Pw7 aEApaClPIL1368Ddq3O4g== X-UI-Out-Filterresults: notjunk:1;V03:K0:PbF5q9U/i24=:Y0p8UUP/w9/KmJ8KfVF8gb bqJISJDD+FbAQo7JX1wpihLmWv3GIyhYnoLLNB5329uBqzDPmUMZ1Uc0br3uLKpbMotIHIXqw DlaI0ZEDLbVUACOjRk65sAfonHug0m5e/FoPJ4llXn4d7hxzgsA3rckkGlA1FaBS1bJUPCA1F XCRgn3/di03LeuUst3ZvqVjgUIBoArIH/qxtONnOIf7rCOF5esn8W4TO/RUIBhl2tInrv6SBQ 9MK3QM2kXa6kK2WGyVmgwCf3arCZMM+ycup4zRX0ku0fZOFOfKeKqj6ZAlG7DIFMkTwgUhr2N LW/gKq8HqXBfzJ2YUfyxv/0Aesq9muZeTEBxNGrasOJt8OX6Kkwfztcc+t0L7E7AUB8uGH6p6 2X3IEP9v+FjaYuZVexUTT6KVT8ibcNWCQTi8fUZp4AhF1QBeUjyvSRG3gnSxwJpELfsuhTBOQ bvSJytBRRRQRG+7GpZsTb1VGcg6dNkTixKe0u6IdyhjRqjkp7BB94I9WAfwPVDEtqeFZP+Bm0 DGRl7+DxTmoS2onUn+g1zgrXUJuIZ3f5G3dfjXWyqItxQ3xPm7h5BjL6wlx/g4/WlYxhwbYpE lPwknst1jGRUo0lqnjt6Edu6dFD9jXzkp0n8XE4G6jVC6SvRJNpkMY0F5fekbnj/m6Y1R0CRR yUYUhghFq8kXD0UIrWx8f2k1cuE9cc4Fy2FlPEzUiWiHlphJ02Ca84HD35Bd/VqoYqm/XouWO oS9aHDDVc5QQ7NR+75X5zuV9n0fTOTOsi5SWqBlHc9F5CPDiQmGJLlpUB7sS64St+tpN4ToQ3 fIfmh+8 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" 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 Reviewed-by: Philippe Mathieu-Daudé --- 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 Thu Oct 20 09:16:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012907 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 1AA38C4321E for ; Thu, 20 Oct 2022 09:31:41 +0000 (UTC) Received: from localhost ([::1]:33602 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRtq-0008K5-UD for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:31:39 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRnG-0007zH-ET for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:24:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57124) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfi-0002vn-HL for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:02 -0400 Received: from mout.kundenserver.de ([212.227.126.187]:33007) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfe-0005Jn-9w for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:00 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N79q8-1pAysu3fUi-017VS6; Thu, 20 Oct 2022 11:16:49 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster , Stefano Brivio Subject: [PATCH v12 11/17] net: dgram: move mcast specific code from net_socket_fd_init_dgram() Date: Thu, 20 Oct 2022 11:16:18 +0200 Message-Id: <20221020091624.48368-12-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:w313p5ImLNBy36kYT1Vgur1moYxt96YT1Aiwmf58eBA7/xEHMzc b21rcM3BpwQUortEr8F8bAFyoTWLGWaia8sNDwxWeWUmalEgvnZcmcxsXkfZ8EctxnDPM4p frr3NtC8EfJn/9UOfy7QChYVBzakndwO2ie6i9+7EoyPzsify8zlogOaFmtDDuwBejaC0XR WFFBi6uChye9SvulVXiQA== X-UI-Out-Filterresults: notjunk:1;V03:K0:3vzTTy9u2mA=:HSIqEAqkM9uulHcpG4kn/c evZZZMqF2UK7Qn+GRzQIxC6IHUK2lvoiuagvrixu/0lvPrF0VmjKLrLcVqK3xA2TGivrXz/pG 6/3nckK+DLT+Pmr+l/7oq+IdLx6LEkHMXx/Sr38wguzJYv8CYV/FCW4RjniwkaJo/xbRgcqvg XzqcTYnbrDGywpgEMcMJ4GYNmkyoRzfG0bSLAYkkQ1LjBHUc2xdhIm4XGqXfv8jIMvaLg+25y iiGnKM/HVPfvlk+avD8SE33XgWZV+As56kcPTXmbPnBeyWDisQVmL4WAK9ZEcSkLhNfm989z5 njsxzNLziGW/JybbaWCJzNlmD81IHycMVV05g8M3O5xPkvYiwV7lG8iTcXBVLw0qTiLEh+5KK snAOznFCMcYjhlXcJ5Ho0VHk03QDliSQWKkPYw6Qj8Ec7lqYWO+bR8Wl9CmWaOWMDep8vCzAe V64VDeV4ppOiV8fyMGQ7UgXB4uTsdy3p7Pg19dmpfK9AuxNh2cuynnju4VIxE3cmeV7mVi2RE XVMZrdxRBByRNIVbl7xTXzoKXTVgiQVKygP2pltRK42kype88P/u0uX601wf+bE8rkozICnuH J+2zBDjIsE5cWskCIzfLoOzJXOAn9DaOFeyTbHsdNRaBuiLdLKdIZFi1J+xkFitiCuY4pOpKY WZR+KnFdYLsCstYCqXEfqY2/RoN01pytI5Fdt1XVJ/5bNpa7b0lXEDIZPrPngICrD1/t8M4xG 3gpMvDBXXmsuW10L3HOVXlq2kQBA9XCK/jcZunw544F3LK4KyzGxqXBo1WNFVrTnL4AEP37Sy 031dbqy Received-SPF: permerror client-ip=212.227.126.187; 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 Thu Oct 20 09:16:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012946 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 42D2CC4332F for ; Thu, 20 Oct 2022 10:04:39 +0000 (UTC) Received: from localhost ([::1]:51288 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olSPl-0006vh-SI for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 06:04:38 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRwm-0001qz-VE for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:34:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57126) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfk-000307-Aa for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:04 -0400 Received: from mout.kundenserver.de ([212.227.126.187]:60183) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfi-0005K8-AP for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:04 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MMGZS-1oVZFE1lEk-00JNv6; Thu, 20 Oct 2022 11:16:50 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster , Stefano Brivio Subject: [PATCH v12 12/17] net: dgram: add unix socket Date: Thu, 20 Oct 2022 11:16:19 +0200 Message-Id: <20221020091624.48368-13-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:BVZEx5zvFGBOysZ1DDE1pAa5ophVRfiUasBIqXl9s0Eso95KI5c P1qLV0nQ6xqpZgLe+bFJ41uUJxk/1gu1rq6fQbaJISXUwsgNDhtD0Jlu3+o8ktyvqeWxjtM N/WtShaYg09S9N+AFDB2pRfSBUPtPsOawMZdffykNOijJRmZLf+zbEOkxWhRxlUwa14DeCi 8hdBZWoVo4RTLK4UQQEPg== X-UI-Out-Filterresults: notjunk:1;V03:K0:PyQrMzdLpxs=:tfWoNznLtpDAoxYGj9QDcu kJ3KjYTfFxe/hY6YjwJr9OYHc+IpcTDsagRzYPoH3VWNmb5Ff+PtHvvoAU79Wb8JnficAuieJ aXUBrcS70CYHBdNO0TSn/yC4rZiz+lLbpNj3bZkOX2hcrdX3MTdJsL2FAQPC4hxcOmSmcDpmz EPIcwLTFB8bkjrfWX2oLsqdjGeMrOhBmqXBnJsoo8NZ1C8HDsRo7C07IEd+OlipKBP4CsbsiK mOJy3hRxoeO40vL8GkiQexUtIMWHmx0N9i2xytgH//AsymdC8vP0xGujP0pTot1UQIvdTL107 AeAyZliftb50BhCHkQ9o4gujcT8E69Ul+zR8G5RU5nIHl6X/BkUtP4oUZv/TxerL04aX0PpPq LyWPctknmuwGVVRn1Gzm+5y6StciJbAqV3SwwkJw/WJ2QHBqhNzFK2VA2x1+1880d2IOJ6Gt2 QFX7r8NjVygVI9HBiNoW7vXWAoEH6ksXfjU6JxYrX1+vXJEpro/fAcSI4vcPjLYWvIyGtaXTY p1Q1oI+yZ61sNoxYXSPvZTi4an3RftZy7pjD6yrnpIYLRZ8z6mkUGte4dOVl1EOSrwAnvqpyE E38X0yyPK///63k8sdYp8r9FOyHg5INB7iP8j0PCBrKs29QaPbKIw3alTVPgS2tNMrFHqvOQ1 wWtxzfwxPRdEUdVzfc/X+175M52jIGUeL8WPqc7spKCqj8HRqQ9TAZGHznN0Pe752IcbbO8dv KxrafO9A9+fklzckOutBE7HYPgWqJZgVkcijRfl/VMEVF1JQrhC3Pt8UUTvNvl8ZQwOAhr7+v pJYpLqz Received-SPF: permerror client-ip=212.227.126.187; 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 QAPI schema 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 aed4ce1a97ff..39388b1b6c41 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 98e2595df93b..fafb214cb89f 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2782,6 +2782,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 Thu Oct 20 09:16:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012917 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 8749CC433FE for ; Thu, 20 Oct 2022 09:37:46 +0000 (UTC) Received: from localhost ([::1]:49208 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRzl-0000YK-Hb for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:37:45 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRnK-00087F-GO for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:24:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37174) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfo-00031R-JI for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:08 -0400 Received: from mout.kundenserver.de ([212.227.126.130]:37371) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfi-0005KE-BN for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:08 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N1fei-1pEIGZ3Ki8-0121HK; Thu, 20 Oct 2022 11:16:52 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster Subject: [PATCH v12 13/17] qemu-sockets: move and rename SocketAddress_to_str() Date: Thu, 20 Oct 2022 11:16:20 +0200 Message-Id: <20221020091624.48368-14-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:rJGWwU379FPxWHX7EKlwIFfPbLkhHTKDFEgfXOayClDd2gTEcT+ oV6xW03waYXUS1VRFhF/AtZOp1mZnz3hUd37+lIOR7Qr2oZGWgQUzxlrm6/cyjn5JPWIP+n PDFkh1edn7Obqp2a7EWxqrkMv1K/2cm+xdBBcMVkMpXHom5qecAfmMyMsd5zR26gb0rTJcq viLWz4Hsxps4sKWjtKgPg== X-UI-Out-Filterresults: notjunk:1;V03:K0:BkZIJrYJi+4=:hJYjXXfKDz2YI2/FJmnl+r B4Q7xC4w29QhOGp9DkNCi5m//1zlh1DpafbSQT14LNiWE78h3SUjvBCVsIhRyiU9PzMVQXh2Z PKajA4HcnbItvbnTOTYIoEdTYL4MNCbMz+G1Ar+ps/kSIXY0fKQVw3yC5P+9TRCb80mS55q3E z1FL9sQOVJ7DF4aTv8aFevOiC72sQoDXi/p1mnVSWijUgs0uijar9pvetC5Jana0kvBulMVuI od6VXRjNpg5mBSOyOUxeYsuR96TwrSx2yslsVkviV1dD+esR7jP8zdqd1jRvnHSZamdgx8Uwq DIWbFqFyzuhEkqH9vpqOJEu9z1Oujy7g4AycLa3KiYwLlQ/VjjILCLpBqKOR6+IEHvRcbnC1T 3/kL1o5Hhw6rBGcxI6Ltsw8sLxxDuSrTQk+b/1ntHGyA5b5iLQA6/AXIkrqJWV+Kp9WrFw4cH Unxc+yP8e7S9xmcvzAJCGErzCIhbEI6V9OHJsot0qpJ8EvxuGphzD3P2DUsbhRIAXT8b151VA A2tfWBUhilgvMx69t47d6WWrtAKkzXSNjnO/rpMiG13JUsdNKRaGaDZV+f+qVF5LvqSQLLqLR IZEGejpKiY/+doYZrM0FqRX3qkdZWrclz+7WUaOyejXfbcsb3Gc/sR111+o7h2JStLVnLa02w GGMv7W+o5MJWVd3bQRF6u7yzJJfh+HmfrsO6r0WZ5k1vxkuAe+y4djn2HYkDAIB5WfsGKzO4F vGPEjOntxeThuY5VfM3PP+1CiEUDKS/NjOmg9DONpXU3CXc3k8t5UVbEpgABSSycbH4ZBCdtP I2f7Cfe 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_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , 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 bab86c5537e1..01b789a79e62 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -199,27 +199,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; @@ -382,7 +361,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 Thu Oct 20 09:16:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012918 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 C4515C43217 for ; Thu, 20 Oct 2022 09:37:47 +0000 (UTC) Received: from localhost ([::1]:49570 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRzm-0000fc-D0 for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:37:46 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRnK-00089S-SD for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:24:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37172) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfo-00030n-Dc for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:08 -0400 Received: from mout.kundenserver.de ([212.227.126.134]:40383) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfj-0005KR-3u for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:08 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MmU9R-1pTLD20nab-00iR1r; Thu, 20 Oct 2022 11:16:53 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster Subject: [PATCH v12 14/17] qemu-sockets: update socket_uri() and socket_parse() to be consistent Date: Thu, 20 Oct 2022 11:16:21 +0200 Message-Id: <20221020091624.48368-15-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:rgQCLcousDQDsUdXn8fcuqm3KbUI1+2RE9s9PEwzwWrmGpqhygC 3TlT+Sgui69Z5zdVGUmlkHebz655PARcfVLCQ/KvJEF81vLg7ztPLeAyc+WiE9vFXS0Ke0U PWSKrmFtb1sQriugP6Y0KoWgRM4S5ww0x2CgGWgTupbKNBlwUgwN03mZMn4TadLr3binuh1 Neq97H3AsJvziSz/O8A6g== X-UI-Out-Filterresults: notjunk:1;V03:K0:f+KlwZEvwhI=:YFlSb1mVepcSfLdVtXLjJd xYOMfbFe0SPN90rPR57+qWoX7L+dJbuElF5/3uZmcdMz1dLTXHA4thKT5jdBQUHV+7/kNVTbj CECDYJOJrNbzlr5jsub/ckAPfQj+Lp33Qn7KXEmgTBuCONfO1cr22Px7TAIP1WSqCx16c7lU7 /+1+peF7EcpmMtowx2ryWupqKPVHTdxqk3rjq6WVSld59oDyX8ubdA7zr24hVLDYMPi065gcl d2z7wpSrFYQp1lq8S/r7cWRGgOaG7+vrSh4987vK9SGF5OvRfcnu2RbYvhTRBM3U9guKhrfdA 5FgZ7qKoBDid6yGStQdODyCqGsr8iY4w7v0J/n13QXFw1HqRUuh61cjzqv+LCEFja7N0gB57q +mOlD7Dfvm+i3ilBm0pteTMRiGnJ64nYHWxlRpnEi3cTE9xNdq+w9+Q+q+NQqA37nk9cBFgDG rHbpvAovyOrLMuSJWCTRQdA2z5U5PAg9dM6mKlbs1URIykDggJEAsE9Ogk1WDRcMldr84t2qz sBAHckLdtk/qSTIyP5mECRUfIQunkRRI7pBqnoJO7ABf8gg51k8NWKAM+LYDkNk6B6Ya/0kY0 Vm7B7elbXlLTOxBoL4aXPT82VsT7YNe4jj3zomv1Si4XODkq5AI8KFyd3lB72aB4SUTiAZcQA +6qOIQKU1VFcqyRqKGXTVZVyXRkXD5ul/Rhx6KhTUZ552yndYKLZt8GDpSOdAJqy2VX3SlAaP UKNEJKwHALAD4ylJDXXyH2A6UyYYKldPMz0Cv9mAjDf6MXJdKZ4T3HOR5wNbuBpEZg6YS0Bie IvmwhDa 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_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , 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 Thu Oct 20 09:16:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 13012940 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 8D945C433FE for ; Thu, 20 Oct 2022 10:00:04 +0000 (UTC) Received: from localhost ([::1]:51056 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olSLL-0003EL-9U for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 06:00:03 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRnM-0008LQ-GU for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:24:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37178) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfp-00032A-6O for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:11 -0400 Received: from mout.kundenserver.de ([212.227.126.187]:39307) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfm-0005Kg-GD for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:08 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MYvTs-1oYKgA2Xb6-00UsNq; Thu, 20 Oct 2022 11:16:55 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster Subject: [PATCH v12 15/17] net: stream: move to QIO to enable additional parameters Date: Thu, 20 Oct 2022 11:16:22 +0200 Message-Id: <20221020091624.48368-16-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:wHGzFJjkgnX0SF0hvEV8uXRRuo4IEfk5FT/cjWlUL2jbOtzjJi6 RB0dXw1X1IO1i7djsccgBEh7Oaob0IkQkuePGwgK1NDwdyR2Yml1LwuVZu6itF1/l9bgVdN +SGIdXvG2zLmXf0CgGlCE+DauaMrdJfSEMVsyVrKqrK4iveBE1b49Af94qHrYW4kdkfFGzp /K+XCvAEYVltrYQA4iJ3A== X-UI-Out-Filterresults: notjunk:1;V03:K0:LmwHPnhmhqw=:6CavKPWzcyDq7WGcj4CXUJ BpbG5hm6u7dr2t26GJ2CokxPkWhOwY/CpYFenL9uYcAEFdAFzg536E0v9mSL4/bLds/Cut7o5 NUrNRomHFcbrB1Vn6t7cPZlUXNs6BMzlWf1Ve0jGaxWbn8py66NijdHxmgjKW2ceLUPrJOb45 0t9MZEjL92ecUafoxmxnUTyIAIDZUfD3o8s6VSFfai0+Wz0x2WwiolyTXu2GYoGfdvpLU/faC UG43cSgwHJlMnbdlKPNWByFnKAJv6UJrNBUy/hiIRs3EAo+RzdQpmXRHTHn9+E/4+Q6rIRG8C 1WJ/q46lzdiE1oeyybAlZea4pXrv9Hf2Ho/HEwfEigVEtFrW0u0tBlAparXc21HZqYAtsDmsf 3esmZ2QXdE3J5IqqD9SfgXczVobBnqHlR35kyOc7kABfhh8k0dQYtR4JpnPNds9oEqxeTI1/f sLdMfmw5F6F7BtSAiad8qh2zlwCY9QhIeyU/62+x0YGZ4/BSXaUhurwqmIBoa7e8UW3yCNHF+ Cj4cQSfJBNulMlPxqRv+CPdt+H+BYh8Fy+acQCazoNXhUZwOncJnLNo2QPIkGk9v8Dpns6jSK aUGGnw0klPD2ohcHre5F87YvMH3Ss1Hhm4uusB0fbGKzZzLzvPnvXMl2GIdB5inslSOfQ6GWu huO7fMy3jdWX6+9eiX1XYJutwmhYlbe2AmrwoCfzcC8SGzTUEMdgPsAKhlaRRaPfB0Jbwbteq b6l1zW0LJVig+jvwffb+7/MGaje5PujnWQAhZYjTwJ7OvGV9FDStINxNl7FV+wL5qNx2ayTQr xnQODcT Received-SPF: permerror client-ip=212.227.126.187; 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 884f473018da..95d6b910407d 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 fafb214cb89f..a91f96a264cc 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2772,8 +2772,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 Thu Oct 20 09:16: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: 13012947 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 0987EC4332F for ; Thu, 20 Oct 2022 10:05:26 +0000 (UTC) Received: from localhost ([::1]:51422 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olSQW-0007Pp-Er for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 06:05:24 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRwm-0001qE-W9 for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:34:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37176) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfo-00031Z-Oj for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:11 -0400 Received: from mout.kundenserver.de ([212.227.126.130]:40327) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfm-0005LE-Gl for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:08 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MKbc4-1oXECi1OSi-00L1Xu; Thu, 20 Oct 2022 11:16:56 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster Subject: [PATCH v12 16/17] tests/qtest: netdev: test stream and dgram backends Date: Thu, 20 Oct 2022 11:16:23 +0200 Message-Id: <20221020091624.48368-17-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:mKoEm2c6uKGESGeDD4UCP30II+ylL1uAkXsybSTYn3tzwJ+EeqM 69XnKDEFZ8/x1n5We8WW52bSBLkbqqUXnPj3KJIOcZHz7/E/BmGvtzPUVOcvshLNs1O6enm kh5FVhzKoMxdWARxnt1yjF/OEs+0HsBxeLfMgonS2qcywaGLclb76r4S8tFxb9wXnEXAdVk JY9HaPPqM6One65M8Kx9g== X-UI-Out-Filterresults: notjunk:1;V03:K0:Sb9T4mUE2tY=:LU0MynDLEvbm9vYbsAnCNu Tob6JiR1+LKr7/XSYh/bLyizza80RE+HaaxtnRzyyoZCNyUq+K1EHcm9MNpm8jJfwh73ecY8i mcmfIqDc6LCl4YVpFkQEy1AZ2ZxvqUaLTnfwFqatUpj1jqDhlYT62b7xbNx67WuBFGosl6m7k 9L1yHQEXjCOwWRWPne6ba8NlCop30wRrp3oOcNsoG4FufTFXqHD8l/1z0c95e2+qKZEXlPG2r ENyZ86Wx8h0FqKtVVe49eI118+HOiIOv9WgL4SerNeKsZfjXlK0DNgZPVg2Veidx6+wEg3DPt XmtknmAUYulXVnhBg9ZoG2fRIFLPQwj+NwNhs3qRHgVMPZj4tT/7yc4kMfA38g1I0fcmGlw5c KxK99uF3Ceq8pZZRhSdopED9STm+BQNGfCNR0T/VsyPb3Uce23Mn1fR7Tkf/QJDzzM/9gSwQR l1utqUZkBhvUprBLU6an26PzhDHBVEPWOKQSYNqIuMxcbEdIhfGXpoRf6GgKLef3IXyfjI91i HIMn278f0tdnkF7I8ot09BpQzogR6wAPbU7nwRgibVPzCu7qHxCdpdbRz2+ORyMmFTsKscR/w 1bjeC+tpfvBRGZ4g/uRjXTJdbt7dt9IeKVR5rmDZ9JOaLPWTFswuA4+0QbKOIq60sy9y5fgp/ /zBN5UQ/Tz2zpYUEHxW1ExQX5l9OaIJn85AD7wNK+uBavkfp9bUe6nkk77e1757dJ/HNiFh7u Lx+eEjsUY9y4sifV36ywO6o+uvFhVpMeACrGdpFV9PjTDyVQFbb0ggEQHpcKrl/PPA+flNRfe xXnW411 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 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 c07a5b1a5f43..6953797e4e3e 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 Thu Oct 20 09:16: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: 13012962 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 80C9BC4332F for ; Thu, 20 Oct 2022 10:09:25 +0000 (UTC) Received: from localhost ([::1]:41524 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olSUO-00046o-DD for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 06:09:24 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olRwL-0001PT-V4 for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 05:34:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37180) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfp-00032F-PU for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:11 -0400 Received: from mout.kundenserver.de ([212.227.126.187]:47683) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olRfn-0005LK-Bq for qemu-devel@nongnu.org; Thu, 20 Oct 2022 05:17:09 -0400 Received: from lenovo-t14s.redhat.com ([82.142.8.70]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MnJdE-1pUiej3hw4-00jGVW; Thu, 20 Oct 2022 11:16:58 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , xen-devel@lists.xenproject.org, Eric Blake , Stefano Stabellini , Paolo Bonzini , Greg Kurz , Jason Wang , Anthony Perard , Thomas Huth , David Gibson , "Michael S. Tsirkin" , Laurent Vivier , Samuel Thibault , "Dr. David Alan Gilbert" , Paul Durrant , Stefan Weil , Markus Armbruster Subject: [PATCH v12 17/17] net: stream: add QAPI events to report connection state Date: Thu, 20 Oct 2022 11:16:24 +0200 Message-Id: <20221020091624.48368-18-lvivier@redhat.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:BMDXyw1i1PI1BNI3n7CxEZG2rEIig4qtmnIwVCRGZ8kKuSpDNWI 98LDzrvkBaD9Bb3ATUXF1OOjYAn4yNd4WeYdWUa0WtW9Fr8wNSWKYGoSIrVDEAEiq8Xaztt 0tg5+FMrdIviR82NsvaGYRBpvnCm+GWlexSe/UqcyhbPyPW1f2UGMgPpiB5idNsMbx77bal 7eYe5nvCTOQt8ijOekPkw== X-UI-Out-Filterresults: notjunk:1;V03:K0:5idzqakK7aA=:PdmSNBYPYZN6TfRGlZGxqf uJclGnrR2L7r2m8dJvBYB7KrlSsacFT4neCZ8eMhl1JRDu2DIvQMi9zxNpLKy8Crrt78iZiFZ QfWb8sveZegpSHE0EjeRd6akS9J6nTYRz7r9H0RH3p7bm42bJoCTKkBPtitRMyZak9bo7IVi2 igAYHAoAukxcz2Mz7gKuf0TqKxxlYoqhzQi6t2YXq0Upy9nIE3WJKcDD7lsm/3ODL2l2/fOZ6 OkdPFKWN8Dzqblx+sqORbAyo2hqYurEsDJqAGJEiDfYq8x+Y2N/TAS5On4PRhBocTRV0kVLQT AIXeQK8Lu/3C2XypbG2CJhWvcl4SS2vPxTaiU6FYe3YrAx+vbGOkY5DWXwm20Ofg7y5UoF9eY HVQIgj7ySsUiyz42rfesplZ85mGEne+VxePIMSJxxgTCj4Bq1Ywed8xkLiJr7j023tA5PTRPV ghBPg4jkjPzUfuDnlXbnmcOIvd0I6xYiABPjvxCHPpS3FLqL/CVgmHAZdabkR9H8YVx1QsgAM vRx8S0ngRcl+sScr4hdF7jgfh19V3g4Lc5VYV/vL9toDdnek9+CZXdJ0xA2Da+x3mALebsnqf Lm5ns6V0U5q+LlKEyY+dZpxhNNChd4YFpfra3mfIdUpW1ltJB0LLcLbwjzUd6LknTI3P2cnj0 hXsN9+xgjKzkfthpOpwn2+vrtPKc2Ix9j6rkvlvd14bZ5tkH4Vi67XEU/M+13qUhpsC8EDu9o 7OSM0VF2Y8ZZ5v+lJSEdUwdBmSdcKEJdwTXcDfUsBhHjHg45G35YWAtEKyLdBxKGMYJN0niJg 9tNRCkK Received-SPF: permerror client-ip=212.227.126.187; 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_DISCONNECTED 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 95d6b910407d..8ad757cefbdf 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_disconnected(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 39388b1b6c41..569ab7fd37e3 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_DISCONNECTED: +# +# Emitted when the netdev stream backend is disconnected +# +# @netdev-id: QEMU netdev id that is disconnected +# +# Since: 7.2 +# +# Example: +# +# <- { 'event': 'NETDEV_STREAM_DISCONNECTED', +# 'data': {'netdev-id': 'netdev0'}, +# 'timestamp': {'seconds': 1663330937, 'microseconds': 526695} } +# +## +{ 'event': 'NETDEV_STREAM_DISCONNECTED', + 'data': { 'netdev-id': 'str' } } From patchwork Thu Oct 20 13:40:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= X-Patchwork-Id: 13013608 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 A6230C4332F for ; Thu, 20 Oct 2022 14:37:47 +0000 (UTC) Received: from localhost ([::1]:42702 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olWg6-0001f9-3b for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 10:37:46 -0400 Received: from [::1] (helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1olWak-0002gi-7W for qemu-devel@archiver.kernel.org; Thu, 20 Oct 2022 10:32:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37940) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1olVnD-00045e-2x for qemu-devel@nongnu.org; Thu, 20 Oct 2022 09:41:03 -0400 Received: from mail-wm1-x32d.google.com ([2a00:1450:4864:20::32d]:40823) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1olVnA-0008Aq-TE for qemu-devel@nongnu.org; Thu, 20 Oct 2022 09:41:02 -0400 Received: by mail-wm1-x32d.google.com with SMTP id v130-20020a1cac88000000b003bcde03bd44so2352619wme.5 for ; Thu, 20 Oct 2022 06:40:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=z7KCvtv19kirWeZA/xvT5hmErPlIa+O7OEhUtObXacc=; b=spjsr+bylW1Wkz69XdSvVrvLSUrIrji9xIQucUYCLqsik0qBuHNw1ojRql6wzTNatx 5Z6fqrBtX3dOhmONND8ztgxF7yJDmg2oHOKYVrDYt6iLAYPIy3991Px0Urp+fJ1Ijz5l f7rmHLlTBXC9cArMldUh0c0H9bHaFs3WJr4ou+jUM7bZs6TvA6DBZOXMiuspGzDq4DV+ Qkkc9ycsroTRXXqYsfPTYJMIYHaTPlom+qaPJ0jvvqzZkYG10R2mgV8/8Il0uclv1VsI FGNAWVqJpv90iLkYG14ExT80yX1/JwCqk4TvgAmoW42H7qWxKzdu6u0ixgxdY2eH8bvX 9SaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=z7KCvtv19kirWeZA/xvT5hmErPlIa+O7OEhUtObXacc=; b=QIfoHPNxTrxB8IzFTgN8T/YxnXkYomGqoKZlz4EuVIkdcFxiXlzuTZUubGG/sw0F2C 6UBAhUyoZMoDsdNZqPtlek+zOnQCq6YixNjij4fNDZj/22sW5+99w19PDXBbU4wz4KNt ikmFfnbJv8ZJw5uhT9EK7q1O/0FvACfWrIF+PGuRTpgCTPZvuCYhgcylh6uTtXa9+UQB 7Yd2o7h6yKz9RzygAJxpJotWVTXHfFP8KQ7r0HjcLq29TBYGfJdlTIpUE+KW6YCkeKO6 2NMtmC4jjzJn88q+W1PbyIjwiJaqQY4BQ1bHx0Cb0qtnKrOFmHEKcVtQqNF84GUCQzuA UySw== X-Gm-Message-State: ACrzQf3m4bzgRpc+x2T+Pn25JfCXcd1LJyDlRAl1v3cfwwc42XD5k/TD /2fK2QFGADSrPka+dBeTMgE3M4jMVN1Ir4Vp/0A= X-Google-Smtp-Source: AMsMyM7ZdRTDvg0KTej2JCoBod9AfQTwgYxxJgI4ywt1UAE3NOndz7ldGZJF+b2XxiwXHcpm8KCSGg== X-Received: by 2002:a1c:f20e:0:b0:3c2:5062:4017 with SMTP id s14-20020a1cf20e000000b003c250624017mr29500438wmc.175.1666273257677; Thu, 20 Oct 2022 06:40:57 -0700 (PDT) Received: from localhost.localdomain (ec2-54-194-108-71.eu-west-1.compute.amazonaws.com. [54.194.108.71]) by smtp.gmail.com with ESMTPSA id r9-20020a05600c458900b003b47b913901sm5685134wmo.1.2022.10.20.06.40.52 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 20 Oct 2022 06:40:53 -0700 (PDT) From: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Cc: Thomas Huth , Paolo Bonzini , Laurent Vivier , =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , =?utf-8?q?Phil?= =?utf-8?q?ippe_Mathieu-Daud=C3=A9?= Subject: [RFC PATCH 18/17] util/qemu-sockets: Display IPv6 addresses within square brackets Date: Thu, 20 Oct 2022 15:40:51 +0200 Message-Id: <20221020134051.88449-1-philmd@linaro.org> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221020091624.48368-1-lvivier@redhat.com> References: <20221020091624.48368-1-lvivier@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32d; envelope-from=philmd@linaro.org; helo=mail-wm1-x32d.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" See RFC3986 "Uniform Resource Identifier (URI): Generic Syntax" section 3.2.2. 'Host' [1]: A host identified by an Internet Protocol literal address, version 6 [RFC3513] or later, is distinguished by enclosing the IP literal within square brackets ("[" and "]"). This is the only place where square bracket characters are allowed in the URI syntax. and RFC5952 "A Recommendation for IPv6 Address Text Representation" section 6. 'Notes on Combining IPv6 Addresses with Port Numbers' [2]: The [] style as expressed in [RFC3986] SHOULD be employed, and is the default unless otherwise specified. [...] For URIs containing IPv6 address literals, [RFC3986] MUST be followed [...]. [1] https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2 [2] https://www.rfc-editor.org/rfc/rfc5952#section-6 Signed-off-by: Philippe Mathieu-Daudé --- tests/qtest/netdev-socket.c | 4 ++-- util/qemu-sockets.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c index 4ea66b4c69..65f0e01db1 100644 --- a/tests/qtest/netdev-socket.c +++ b/tests/qtest/netdev-socket.c @@ -134,13 +134,13 @@ static void test_stream_inet_ipv6(void) "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", + 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", ':'); + EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:[::1]", ':'); qtest_quit(qts1); qtest_quit(qts0); diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index a9926af714..19af96fa2c 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -1081,8 +1081,10 @@ char *socket_uri(SocketAddress *addr) { switch (addr->type) { case SOCKET_ADDRESS_TYPE_INET: - return g_strdup_printf("tcp:%s:%s", + return g_strdup_printf("tcp:%s%s%s:%s", + addr->u.inet.ipv6 ? "[" : "", addr->u.inet.host, + addr->u.inet.ipv6 ? "]" : "", addr->u.inet.port); case SOCKET_ADDRESS_TYPE_UNIX: return g_strdup_printf("unix:%s",