diff options
author | Cristian Ciocaltea <cristian.ciocaltea@collabora.com> | 2023-09-13 00:42:01 +0300 |
---|---|---|
committer | Cristian Ciocaltea <cristian.ciocaltea@collabora.com> | 2023-09-13 00:42:01 +0300 |
commit | f57671f6978c109b9f6727117f71967c3b5cdd96 (patch) | |
tree | cc435b04cf66de458a84d7d8c85ad671e87bc019 | |
parent | 51ac122641823209b6249d9670e774466aa6c48b (diff) | |
parent | ef76035f50a1147a0d39b3d9c1b80b92a2961028 (diff) | |
download | linux-f57671f6978c109b9f6727117f71967c3b5cdd96.tar.gz |
Merge branch 6.1/features/tcp-timewait
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
-rw-r--r-- | include/net/tcp.h | 29 | ||||
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 8 |
2 files changed, 33 insertions, 4 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index e9c8f88f4769..27039f55ef43 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, @@ -1565,6 +1566,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) { diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 42844d20da02..607d4258416d 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -142,7 +142,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, tcptw->tw_ts_recent = tmp_opt.rcv_tsval; } - inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN); + inet_twsk_reschedule(tw, tcp_timewait_len(tw)); return TCP_TW_ACK; } @@ -179,7 +179,7 @@ kill: return TCP_TW_SUCCESS; } } else { - inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN); + inet_twsk_reschedule(tw, tcp_timewait_len(tw)); } if (tmp_opt.saw_tstamp) { @@ -230,7 +230,7 @@ kill: * Do not reschedule in the last case. */ if (paws_reject || th->ack) - inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN); + inet_twsk_reschedule(tw, tcp_timewait_len(tw)); return tcp_timewait_check_oow_rate_limit( tw, skb, LINUX_MIB_TCPACKSKIPPEDTIMEWAIT); @@ -308,7 +308,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) timeo = rto; if (state == TCP_TIME_WAIT) - timeo = TCP_TIMEWAIT_LEN; + timeo = tcp_timewait_len(tw); /* tw_timer is pinned, so we need to make sure BH are disabled * in following section, otherwise timer handler could run before |