From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202502 header.b=cioHDi6E; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 746415A0274 for ; Wed, 19 Mar 2025 06:14:29 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202502; t=1742361265; bh=nudCOxdWIQRjWBV7zwVTOkB+eIVReG9djJaYKLspOjU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cioHDi6EAUwzDgf610de96DsmnnkF5p7ObjUG5Yc+kG92vOp9I0UA3BnNVMEQX/I2 5XLII5nVKkcIhyIUSYDbV6z7TWQKKdJMu7ey2XYEf+hMEJ/m5G4ksUKD6cM2NYarBO dttWAGSgfbv4A8bLMNAGOzW5mC3Uw8jh7Ai+ee2w2x7H9ya2iLnTGtmO1geGB6tjZR D3e34ZF703Zwitohaggseptv36z+p2bLu57NwWtjz7o0oQcFb1KRq1ezC0Zz5IeslK y7qfCm8hgm+HQuBaOhZ/eITndaSySXlZCXzbB/UtBt+VlxqgR5zlgoka7xjAHCQwwy +xC1bYcpqlsmQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4ZHcMP165Xz4wcT; Wed, 19 Mar 2025 16:14:25 +1100 (AEDT) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH 2/3] migrate, tcp: Migrate RFC7323 timestamp Date: Wed, 19 Mar 2025 16:14:22 +1100 Message-ID: <20250319051423.2378689-3-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250319051423.2378689-1-david@gibson.dropbear.id.au> References: <20250319051423.2378689-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: CYY27SUUPUWWWRB46XBJQ5Y47CBPRRIS X-Message-ID-Hash: CYY27SUUPUWWWRB46XBJQ5Y47CBPRRIS X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Currently our migration of the state of TCP sockets omits the RFC7323 timestamp. In some circumstances that can result in data sent from the target machine not being received, because it is discarded on the peer due to PAWS checking. Add code to dump and restore the timestamp across migration. Link: https://bugs.passt.top/show_bug.cgi?id=115 Signed-off-by: David Gibson --- tcp.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tcp_conn.h | 2 ++ 2 files changed, 61 insertions(+) diff --git a/tcp.c b/tcp.c index 163ddd60..56df1636 100644 --- a/tcp.c +++ b/tcp.c @@ -2861,6 +2861,57 @@ static int tcp_flow_dump_mss(const struct tcp_tap_conn *conn, return 0; } + +/** + * tcp_flow_dump_timestamp() - Dump RFC7323 timestamp via TCP_TIMESTAMP + * @conn: Pointer to the TCP connection structure + * @t: Extended migration data (tcpi_options must be populated) + * + * Return: 0 on success, negative error code on failure + */ +static int tcp_flow_dump_timestamp(const struct tcp_tap_conn *conn, + struct tcp_tap_transfer_ext *t) +{ + int val = 0; + + if (t->tcpi_options & TCPI_OPT_TIMESTAMPS) { + socklen_t sl = sizeof(val); + + if (getsockopt(conn->sock, SOL_TCP, TCP_TIMESTAMP, &val, &sl)) { + int rc = -errno; + flow_perror(conn, "Getting RFC7323 timestamp"); + return rc; + } + } + + t->timestamp = (uint32_t)val; + return 0; +} + +/** + * tcp_flow_repair_timestamp() - Restore RFC7323 timestamp via TCP_TIMESTAMP + * @conn: Pointer to the TCP connection structure + * @t: Extended migration data + * + * Return: 0 on success, negative error code on failure + */ +static int tcp_flow_repair_timestamp(const struct tcp_tap_conn *conn, + const struct tcp_tap_transfer_ext *t) +{ + int val = (int)t->timestamp; + + if (t->tcpi_options & TCPI_OPT_TIMESTAMPS) { + if (setsockopt(conn->sock, SOL_TCP, TCP_TIMESTAMP, + &val, sizeof(val))) { + int rc = -errno; + flow_perror(conn, "Setting RFC7323 timestamp"); + return rc; + } + } + + return 0; +} + /** * tcp_flow_dump_wnd() - Dump current tcp_repair_window parameters * @conn: Pointer to the TCP connection structure @@ -3260,6 +3311,9 @@ int tcp_flow_migrate_source_ext(int fd, const struct tcp_tap_conn *conn) if ((rc = tcp_flow_dump_mss(conn, t))) goto fail; + if ((rc = tcp_flow_dump_timestamp(conn, t))) + goto fail; + if ((rc = tcp_flow_dump_wnd(conn, t))) goto fail; @@ -3305,6 +3359,7 @@ int tcp_flow_migrate_source_ext(int fd, const struct tcp_tap_conn *conn) t->notsent = htonl(t->notsent); t->rcvq = htonl(t->rcvq); t->mss = htonl(t->mss); + t->timestamp = htonl(t->timestamp); t->snd_wl1 = htonl(t->snd_wl1); t->snd_wnd = htonl(t->snd_wnd); @@ -3519,6 +3574,7 @@ int tcp_flow_migrate_target_ext(struct ctx *c, struct tcp_tap_conn *conn, int fd t.notsent = ntohl(t.notsent); t.rcvq = ntohl(t.rcvq); t.mss = ntohl(t.mss); + t.timestamp = ntohl(t.timestamp); t.snd_wl1 = ntohl(t.snd_wl1); t.snd_wnd = ntohl(t.snd_wnd); @@ -3561,6 +3617,9 @@ int tcp_flow_migrate_target_ext(struct ctx *c, struct tcp_tap_conn *conn, int fd /* We weren't able to create the socket, discard flow */ goto fail; + if (tcp_flow_repair_timestamp(conn, &t)) + goto fail; + if (tcp_flow_select_queue(conn, TCP_SEND_QUEUE)) goto fail; diff --git a/tcp_conn.h b/tcp_conn.h index 9126a36f..c79f558b 100644 --- a/tcp_conn.h +++ b/tcp_conn.h @@ -152,6 +152,7 @@ struct tcp_tap_transfer { * @notsent: Part of pending send queue that wasn't sent out yet * @rcvq: Length of pending receive queue * @mss: Socket-side MSS clamp + * @timestamp: RFC7323 timestamp * @snd_wl1: Next sequence used in window probe (next sequence - 1) * @snd_wnd: Socket-side sending window * @max_window: Window clamp @@ -171,6 +172,7 @@ struct tcp_tap_transfer_ext { uint32_t rcvq; uint32_t mss; + uint32_t timestamp; /* We can't just use struct tcp_repair_window: we need network order */ uint32_t snd_wl1; -- 2.48.1