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=202512 header.b=a88isvp9; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 0E2DA5A0623 for ; Thu, 29 Jan 2026 06:54:00 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202512; t=1769666037; bh=Qvt/nZUnsEkF+AAqcV/VIDaFdOo0nLtCfbg8kKGeDJo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a88isvp98631+Rh/DaDY3E07Ic3MLa3TplD/s9k+LyKZlz8gyRgsd2Ugxtscy2ba9 o60CoCqzEnEeVA8+G9gAy17hRh1ZzNziFeIa5IB7xjehgq1i9E0iQu36FfTuMS/uj3 NHmHkngOVd0JL92JugrkvFzOy2yhAvBzA+JifPSzGfdkS4h5/KOR/90TwWgNWhM6yU nfUFcqpNCikC6e0UkCz1k1fQetW7toWJgiwyu85i+fyvwwkXb82m6AGrPXVQuu64mR KFEJ9uhtzquXIY6YKroT9QkyANPjpcfOfhPSXnyGMpIUtsccGSAyN87Vd/zW8wirlo Fvc3MLz8+np8w== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4f1pH95yQ7z4wGX; Thu, 29 Jan 2026 16:53:57 +1100 (AEDT) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH 2/2] tcp: Eliminate FIN_TIMEOUT Date: Thu, 29 Jan 2026 16:53:55 +1100 Message-ID: <20260129055355.1229700-3-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260129055355.1229700-1-david@gibson.dropbear.id.au> References: <20260129055355.1229700-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: AU7WORF5DXNLAUVES3UOZUK4BSRF2RMB X-Message-ID-Hash: AU7WORF5DXNLAUVES3UOZUK4BSRF2RMB 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: >From the name, and it's value of 60s, FIN_TIMEOUT appears to be defined as an equivalent to the kernel's net.ipv4.tcp_fin_timeout sysctl, which controls how long the kernel will keep an orphaned (that is, closed by userspace) socket which is in FIN_WAIT_2 state. The theory of operation describes FIN_TIMEOUT thus: - FIN_TIMEOUT: if a FIN segment was acknowledged by tap/guest and a FIN segment (write shutdown) was sent via socket (events SOCK_FIN_SENT and TAP_FIN_ACKED), but no socket activity is detected from the socket within this time, reset the connection This description does not match what net.ipv4.tcp_fin_timeout does. The test for SOCK_FIN_SENT does not check if we are in FIN_WAIT_2 or for an orphaned socket. In fact SOCK_FIN_SENT means we *cannot* be in FIN_WAIT_2 state (w.r.t. the tap side): we set it when we shutdown(SHUT_WR) the socket connection. We do that only when we receive a FIN from the tap side, and the TCP state diagram does not allow us to be in FIN_WAIT_2 state if we already have a FIN from our peer. The description also doesn't match what the code does: in tcp_timer_ctl() we only set FIN_TIMEOUT on our timer when when ACK_FROM_TAP_DUE is unset, but we only act on the FIN_TIMEOUT if ACK_FROM_TAP_DUE *is* set. In fact it's impossible for us to implement something like net.ipv4.tcp_fin_timeout, because recognizing an orphaned socket requires out of band information (the fact the socket has been closed) that an endpoint kernel has, but is not visible to us (via either tap or socket interface). Therefore, entirely remove the FIN_TIMEOUT related logic. Signed-off-by: David Gibson --- tcp.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/tcp.c b/tcp.c index dbfde2e0..0be871a4 100644 --- a/tcp.c +++ b/tcp.c @@ -190,11 +190,6 @@ * - RTO_INIT_AFTER_SYN_RETRIES: if SYN retries happened during handshake and * RTO is less than this, re-initialise RTO to this for data retransmissions * - * - FIN_TIMEOUT: if a FIN segment was acknowledged by tap/guest and a FIN - * segment (write shutdown) was sent via socket (events SOCK_FIN_SENT and - * TAP_FIN_ACKED), but no socket activity is detected from the socket within - * this time, reset the connection - * * - ACT_TIMEOUT, in the presence of any event: if no activity is detected on * either side, the connection is reset * @@ -341,7 +336,6 @@ enum { #define RTO_INIT 1 /* s, RFC 6298 */ #define RTO_INIT_AFTER_SYN_RETRIES 3 /* s, RFC 6298 */ -#define FIN_TIMEOUT 60 #define ACT_TIMEOUT 7200 #define LOW_RTT_TABLE_SIZE 8 @@ -594,8 +588,6 @@ static void tcp_timer_ctl(const struct ctx *c, struct tcp_tap_conn *conn) timeout = MAX(timeout, RTO_INIT_AFTER_SYN_RETRIES); timeout <<= MAX(exp, 0); it.it_value.tv_sec = MIN(timeout, c->tcp.rto_max); - } else if (CONN_HAS(conn, SOCK_FIN_SENT | TAP_FIN_ACKED)) { - it.it_value.tv_sec = FIN_TIMEOUT; } else { it.it_value.tv_sec = ACT_TIMEOUT; } @@ -715,9 +707,6 @@ void conn_event_do(const struct ctx *c, struct tcp_tap_conn *conn, flow_hash_remove(c, TAP_SIDX(conn)); tcp_epoll_ctl(conn); } - - if (CONN_HAS(conn, SOCK_FIN_SENT | TAP_FIN_ACKED)) - tcp_timer_ctl(c, conn); } /** @@ -2590,9 +2579,6 @@ void tcp_timer_handler(const struct ctx *c, union epoll_ref ref) conn_flag(c, conn, SYN_RETRIED); tcp_timer_ctl(c, conn); } - } else if (CONN_HAS(conn, SOCK_FIN_SENT | TAP_FIN_ACKED)) { - flow_dbg(conn, "FIN timeout"); - tcp_rst(c, conn); } else if (conn->retries == TCP_MAX_RETRIES) { flow_dbg(conn, "retransmissions count exceeded"); tcp_rst(c, conn); -- 2.52.0