summary refs log tree commit diff
path: root/include/net/tcp.h
diff options
context:
space:
mode:
authorPaul Gofman <pgofman@codeweavers.com>2022-02-16 18:41:40 -0300
committerCristian Ciocaltea <cristian.ciocaltea@collabora.com>2022-12-12 17:57:15 +0200
commitef76035f50a1147a0d39b3d9c1b80b92a2961028 (patch)
tree08c7848a52d5b73257f8a36d8b02449b8e9294de /include/net/tcp.h
parent830b3c68c1fb1e9176028d02ef86f3cf76aa2476 (diff)
downloadlinux-ef76035f50a1147a0d39b3d9c1b80b92a2961028.tar.gz
tcp: Also use tcp_fin_timeout as TCP TIME_WAIT timeout for loopback connections
On loopback connections, reuse the configured tpc_fin_timeout to kill the
socket regardless of the socket state. This is done to make sure apps
that were killed can always quickly reuse their TCP port instead of waiting
for one minute to do so.

https://gitlab.steamos.cloud/jupiter/tasks/-/issues/429
Signed-off-by: André Almeida <andrealmeid@collabora.com>
(cherry picked from commit f90f986107f1bf0b270f6ff69dd7e58530459db7)
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Diffstat (limited to 'include/net/tcp.h')
-rw-r--r--include/net/tcp.h29
1 files changed, 29 insertions, 0 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 14d45661a84d..6517a6798d6f 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -122,6 +122,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
 
 #define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
 				  * state, about 60 seconds	*/
+#define TCP_TIMEWAIT_LEN_MIN (1*HZ)
 #define TCP_FIN_TIMEOUT	TCP_TIMEWAIT_LEN
                                  /* BSD style FIN_WAIT2 deadlock breaker.
 				  * It used to be 3min, new value is 60sec,
@@ -1549,6 +1550,34 @@ static inline int tcp_fin_time(const struct sock *sk)
 	return fin_timeout;
 }
 
+static inline int tcp_timewait_len(const struct inet_timewait_sock *tw)
+{
+	bool loopback = false;
+
+	if (tw->tw_bound_dev_if == LOOPBACK_IFINDEX)
+		loopback = true;
+#if IS_ENABLED(CONFIG_IPV6)
+	else if (tw->tw_family == AF_INET6) {
+		if (ipv6_addr_loopback(&tw->tw_v6_daddr) ||
+			ipv6_addr_v4mapped_loopback(&tw->tw_v6_daddr) ||
+			ipv6_addr_loopback(&tw->tw_v6_rcv_saddr) ||
+			ipv6_addr_v4mapped_loopback(&tw->tw_v6_rcv_saddr))
+			loopback = true;
+	}
+#endif
+	else
+	{
+		if (ipv4_is_loopback(tw->tw_daddr) ||
+			ipv4_is_loopback(tw->tw_rcv_saddr))
+			loopback = true;
+	}
+
+	if (!loopback)
+		return TCP_TIMEWAIT_LEN;
+
+	return max(TCP_TIMEWAIT_LEN_MIN, sock_net((const struct sock*)tw)->ipv4.sysctl_tcp_fin_timeout);
+}
+
 static inline bool tcp_paws_check(const struct tcp_options_received *rx_opt,
 				  int paws_win)
 {