From nobody Tue Feb 10 03:39:41 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1493484910045820.7430624010244; Sat, 29 Apr 2017 09:55:10 -0700 (PDT) Received: from localhost ([::1]:41751 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d4VeG-0003Sc-Kd for importer@patchew.org; Sat, 29 Apr 2017 12:55:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39289) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d4VXM-0006ve-6q for qemu-devel@nongnu.org; Sat, 29 Apr 2017 12:48:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d4VXK-0001Nh-DB for qemu-devel@nongnu.org; Sat, 29 Apr 2017 12:48:00 -0400 Received: from hera.aquilenet.fr ([2a01:474::1]:55429) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d4VXK-0001N8-4D for qemu-devel@nongnu.org; Sat, 29 Apr 2017 12:47:58 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id 995A2BBCC; Sat, 29 Apr 2017 18:47:57 +0200 (CEST) Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 84lUVcPfNXLz; Sat, 29 Apr 2017 18:47:56 +0200 (CEST) Received: from var.youpi.perso.aquilenet.fr (unknown [IPv6:2a01:cb19:181:c200:3602:86ff:fe2c:6a19]) by hera.aquilenet.fr (Postfix) with ESMTPSA id 3EC0EBD11; Sat, 29 Apr 2017 18:47:52 +0200 (CEST) Received: from samy by var.youpi.perso.aquilenet.fr with local (Exim 4.89) (envelope-from ) id 1d4VXD-0004Xw-6S; Sat, 29 Apr 2017 18:47:51 +0200 X-Virus-Scanned: Debian amavisd-new at aquilenet.fr From: Samuel Thibault To: qemu-devel@nongnu.org Date: Sat, 29 Apr 2017 18:47:49 +0200 Message-Id: <20170429164750.17414-9-samuel.thibault@ens-lyon.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170429164750.17414-1-samuel.thibault@ens-lyon.org> References: <20170429164750.17414-1-samuel.thibault@ens-lyon.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a01:474::1 Subject: [Qemu-devel] [PULL 8/9] slirp: VMStatify socket level X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jan.kiszka@siemens.com, "Dr. David Alan Gilbert" , stefanha@redhat.com, Samuel Thibault Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: "Dr. David Alan Gilbert" Working up the stack, this replaces the slirp_socket_load/save with VMState definitions. A place holder for IPv6 support is added as a comment; it needs testing once the rest of the IPv6 code is there. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Samuel Thibault --- slirp/slirp.c | 219 +++++++++++++++++++++++++++++++++++++----------------= ---- slirp/socket.h | 6 +- 2 files changed, 145 insertions(+), 80 deletions(-) diff --git a/slirp/slirp.c b/slirp/slirp.c index 8fc4e8df73..c3426648e5 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -1254,40 +1254,154 @@ static const VMStateDescription vmstate_slirp_sbuf= =3D { } }; =20 +static bool slirp_older_than_v4(void *opaque, int version_id) +{ + return version_id < 4; +} =20 -static void slirp_socket_save(QEMUFile *f, struct socket *so) +static bool slirp_family_inet(void *opaque, int version_id) { - qemu_put_be32(f, so->so_urgc); - qemu_put_be16(f, so->so_ffamily); - switch (so->so_ffamily) { - case AF_INET: - qemu_put_be32(f, so->so_faddr.s_addr); - qemu_put_be16(f, so->so_fport); - break; - default: - error_report("so_ffamily unknown, unable to save so_faddr and" - " so_fport"); + union slirp_sockaddr *ssa =3D (union slirp_sockaddr *)opaque; + return ssa->ss.ss_family =3D=3D AF_INET; +} + +static int slirp_socket_pre_load(void *opaque) +{ + struct socket *so =3D opaque; + if (tcp_attach(so) < 0) { + return -ENOMEM; } - qemu_put_be16(f, so->so_lfamily); - switch (so->so_lfamily) { - case AF_INET: - qemu_put_be32(f, so->so_laddr.s_addr); - qemu_put_be16(f, so->so_lport); + /* Older versions don't load these fields */ + so->so_ffamily =3D AF_INET; + so->so_lfamily =3D AF_INET; + return 0; +} + +#ifndef _WIN32 +#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_UINT32_TEST(f, s, t) +#else +/* Win uses u_long rather than uint32_t - but it's still 32bits long */ +#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_SINGLE_TEST(f, s, t, 0, \ + vmstate_info_uint32, u_long) +#endif + +/* The OS provided ss_family field isn't that portable; it's size + * and type varies (16/8 bit, signed, unsigned) + * and the values it contains aren't fully portable. + */ +typedef struct SS_FamilyTmpStruct { + union slirp_sockaddr *parent; + uint16_t portable_family; +} SS_FamilyTmpStruct; + +#define SS_FAMILY_MIG_IPV4 2 /* Linux, BSD, Win... */ +#define SS_FAMILY_MIG_IPV6 10 /* Linux */ +#define SS_FAMILY_MIG_OTHER 0xffff + +static void ss_family_pre_save(void *opaque) +{ + SS_FamilyTmpStruct *tss =3D opaque; + + tss->portable_family =3D SS_FAMILY_MIG_OTHER; + + if (tss->parent->ss.ss_family =3D=3D AF_INET) { + tss->portable_family =3D SS_FAMILY_MIG_IPV4; + } else if (tss->parent->ss.ss_family =3D=3D AF_INET6) { + tss->portable_family =3D SS_FAMILY_MIG_IPV6; + } +} + +static int ss_family_post_load(void *opaque, int version_id) +{ + SS_FamilyTmpStruct *tss =3D opaque; + + switch (tss->portable_family) { + case SS_FAMILY_MIG_IPV4: + tss->parent->ss.ss_family =3D AF_INET; + break; + case SS_FAMILY_MIG_IPV6: + case 23: /* compatibility: AF_INET6 from mingw */ + case 28: /* compatibility: AF_INET6 from FreeBSD sys/socket.h */ + tss->parent->ss.ss_family =3D AF_INET6; break; default: - error_report("so_ffamily unknown, unable to save so_laddr and" - " so_lport"); + error_report("invalid ss_family type %x", tss->portable_family); + return -EINVAL; } - qemu_put_byte(f, so->so_iptos); - qemu_put_byte(f, so->so_emu); - qemu_put_byte(f, so->so_type); - qemu_put_be32(f, so->so_state); - /* TODO: Build vmstate at this level */ - vmstate_save_state(f, &vmstate_slirp_sbuf, &so->so_rcv, 0); - vmstate_save_state(f, &vmstate_slirp_sbuf, &so->so_snd, 0); - vmstate_save_state(f, &vmstate_slirp_tcp, so->so_tcpcb, 0); + + return 0; } =20 +static const VMStateDescription vmstate_slirp_ss_family =3D { + .name =3D "slirp-socket-addr/ss_family", + .pre_save =3D ss_family_pre_save, + .post_load =3D ss_family_post_load, + .fields =3D (VMStateField[]) { + VMSTATE_UINT16(portable_family, SS_FamilyTmpStruct), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_slirp_socket_addr =3D { + .name =3D "slirp-socket-addr", + .version_id =3D 4, + .fields =3D (VMStateField[]) { + VMSTATE_WITH_TMP(union slirp_sockaddr, SS_FamilyTmpStruct, + vmstate_slirp_ss_family), + VMSTATE_SIN4_ADDR(sin.sin_addr.s_addr, union slirp_sockaddr, + slirp_family_inet), + VMSTATE_UINT16_TEST(sin.sin_port, union slirp_sockaddr, + slirp_family_inet), + +#if 0 + /* Untested: Needs checking by someone with IPv6 test */ + VMSTATE_BUFFER_TEST(sin6.sin6_addr, union slirp_sockaddr, + slirp_family_inet6), + VMSTATE_UINT16_TEST(sin6.sin6_port, union slirp_sockaddr, + slirp_family_inet6), + VMSTATE_UINT32_TEST(sin6.sin6_flowinfo, union slirp_sockaddr, + slirp_family_inet6), + VMSTATE_UINT32_TEST(sin6.sin6_scope_id, union slirp_sockaddr, + slirp_family_inet6), +#endif + + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_slirp_socket =3D { + .name =3D "slirp-socket", + .version_id =3D 4, + .pre_load =3D slirp_socket_pre_load, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(so_urgc, struct socket), + /* Pre-v4 versions */ + VMSTATE_SIN4_ADDR(so_faddr.s_addr, struct socket, + slirp_older_than_v4), + VMSTATE_SIN4_ADDR(so_laddr.s_addr, struct socket, + slirp_older_than_v4), + VMSTATE_UINT16_TEST(so_fport, struct socket, slirp_older_than_v4), + VMSTATE_UINT16_TEST(so_lport, struct socket, slirp_older_than_v4), + /* v4 and newer */ + VMSTATE_STRUCT(fhost, struct socket, 4, vmstate_slirp_socket_addr, + union slirp_sockaddr), + VMSTATE_STRUCT(lhost, struct socket, 4, vmstate_slirp_socket_addr, + union slirp_sockaddr), + + VMSTATE_UINT8(so_iptos, struct socket), + VMSTATE_UINT8(so_emu, struct socket), + VMSTATE_UINT8(so_type, struct socket), + VMSTATE_INT32(so_state, struct socket), + VMSTATE_STRUCT(so_rcv, struct socket, 0, vmstate_slirp_sbuf, + struct sbuf), + VMSTATE_STRUCT(so_snd, struct socket, 0, vmstate_slirp_sbuf, + struct sbuf), + VMSTATE_STRUCT_POINTER(so_tcpcb, struct socket, vmstate_slirp_tcp, + struct tcpcb), + VMSTATE_END_OF_LIST() + } +}; + static void slirp_bootp_save(QEMUFile *f, Slirp *slirp) { int i; @@ -1312,7 +1426,7 @@ static void slirp_state_save(QEMUFile *f, void *opaqu= e) continue; =20 qemu_put_byte(f, 42); - slirp_socket_save(f, so); + vmstate_save_state(f, &vmstate_slirp_socket, so, NULL); } qemu_put_byte(f, 0); =20 @@ -1321,55 +1435,6 @@ static void slirp_state_save(QEMUFile *f, void *opaq= ue) slirp_bootp_save(f, slirp); } =20 -static int slirp_socket_load(QEMUFile *f, struct socket *so, int version_i= d) -{ - int ret =3D 0; - if (tcp_attach(so) < 0) - return -ENOMEM; - - so->so_urgc =3D qemu_get_be32(f); - if (version_id <=3D 3) { - so->so_ffamily =3D AF_INET; - so->so_faddr.s_addr =3D qemu_get_be32(f); - so->so_laddr.s_addr =3D qemu_get_be32(f); - so->so_fport =3D qemu_get_be16(f); - so->so_lport =3D qemu_get_be16(f); - } else { - so->so_ffamily =3D qemu_get_be16(f); - switch (so->so_ffamily) { - case AF_INET: - so->so_faddr.s_addr =3D qemu_get_be32(f); - so->so_fport =3D qemu_get_be16(f); - break; - default: - error_report( - "so_ffamily unknown, unable to restore so_faddr and so_lpo= rt"); - } - so->so_lfamily =3D qemu_get_be16(f); - switch (so->so_lfamily) { - case AF_INET: - so->so_laddr.s_addr =3D qemu_get_be32(f); - so->so_lport =3D qemu_get_be16(f); - break; - default: - error_report( - "so_ffamily unknown, unable to restore so_laddr and so_lpo= rt"); - } - } - so->so_iptos =3D qemu_get_byte(f); - so->so_emu =3D qemu_get_byte(f); - so->so_type =3D qemu_get_byte(f); - so->so_state =3D qemu_get_be32(f); - /* TODO: VMState at this level */ - ret =3D vmstate_load_state(f, &vmstate_slirp_sbuf, &so->so_rcv, 0); - if (!ret) { - ret =3D vmstate_load_state(f, &vmstate_slirp_sbuf, &so->so_snd, 0); - } - if (!ret) { - ret =3D vmstate_load_state(f, &vmstate_slirp_tcp, so->so_tcpcb, 0); - } - return ret; -} =20 static void slirp_bootp_load(QEMUFile *f, Slirp *slirp) { @@ -1393,7 +1458,7 @@ static int slirp_state_load(QEMUFile *f, void *opaque= , int version_id) if (!so) return -ENOMEM; =20 - ret =3D slirp_socket_load(f, so, version_id); + ret =3D vmstate_load_state(f, &vmstate_slirp_socket, so, version_i= d); =20 if (ret < 0) return ret; diff --git a/slirp/socket.h b/slirp/socket.h index c1be77eaf3..2f224bc34f 100644 --- a/slirp/socket.h +++ b/slirp/socket.h @@ -36,7 +36,7 @@ struct socket { * PING reply's */ struct tcpiphdr *so_ti; /* Pointer to the original ti within * so_mconn, for non-blocking connections */ - int so_urgc; + uint32_t so_urgc; union slirp_sockaddr fhost; /* Foreign host */ #define so_faddr fhost.sin.sin_addr #define so_fport fhost.sin.sin_port @@ -54,8 +54,8 @@ struct socket { uint8_t so_iptos; /* Type of service */ uint8_t so_emu; /* Is the socket emulated? */ =20 - u_char so_type; /* Type of socket, UDP or TCP */ - int so_state; /* internal state flags SS_*, below */ + uint8_t so_type; /* Type of socket, UDP or TCP */ + int32_t so_state; /* internal state flags SS_*, below */ =20 struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */ u_int so_expire; /* When the socket will expire */ --=20 2.11.0