18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  net/dccp/timer.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  An implementation of the DCCP protocol
68c2ecf20Sopenharmony_ci *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/dccp.h>
108c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
118c2ecf20Sopenharmony_ci#include <linux/export.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "dccp.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/* sysctl variables governing numbers of retransmission attempts */
168c2ecf20Sopenharmony_ciint  sysctl_dccp_request_retries	__read_mostly = TCP_SYN_RETRIES;
178c2ecf20Sopenharmony_ciint  sysctl_dccp_retries1		__read_mostly = TCP_RETR1;
188c2ecf20Sopenharmony_ciint  sysctl_dccp_retries2		__read_mostly = TCP_RETR2;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic void dccp_write_err(struct sock *sk)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	sk->sk_err = sk->sk_err_soft ? : ETIMEDOUT;
238c2ecf20Sopenharmony_ci	sk->sk_error_report(sk);
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED);
268c2ecf20Sopenharmony_ci	dccp_done(sk);
278c2ecf20Sopenharmony_ci	__DCCP_INC_STATS(DCCP_MIB_ABORTONTIMEOUT);
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/* A write timeout has occurred. Process the after effects. */
318c2ecf20Sopenharmony_cistatic int dccp_write_timeout(struct sock *sk)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	const struct inet_connection_sock *icsk = inet_csk(sk);
348c2ecf20Sopenharmony_ci	int retry_until;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	if (sk->sk_state == DCCP_REQUESTING || sk->sk_state == DCCP_PARTOPEN) {
378c2ecf20Sopenharmony_ci		if (icsk->icsk_retransmits != 0)
388c2ecf20Sopenharmony_ci			dst_negative_advice(sk);
398c2ecf20Sopenharmony_ci		retry_until = icsk->icsk_syn_retries ?
408c2ecf20Sopenharmony_ci			    : sysctl_dccp_request_retries;
418c2ecf20Sopenharmony_ci	} else {
428c2ecf20Sopenharmony_ci		if (icsk->icsk_retransmits >= sysctl_dccp_retries1) {
438c2ecf20Sopenharmony_ci			/* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu
448c2ecf20Sopenharmony_ci			   black hole detection. :-(
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci			   It is place to make it. It is not made. I do not want
478c2ecf20Sopenharmony_ci			   to make it. It is disguisting. It does not work in any
488c2ecf20Sopenharmony_ci			   case. Let me to cite the same draft, which requires for
498c2ecf20Sopenharmony_ci			   us to implement this:
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci   "The one security concern raised by this memo is that ICMP black holes
528c2ecf20Sopenharmony_ci   are often caused by over-zealous security administrators who block
538c2ecf20Sopenharmony_ci   all ICMP messages.  It is vitally important that those who design and
548c2ecf20Sopenharmony_ci   deploy security systems understand the impact of strict filtering on
558c2ecf20Sopenharmony_ci   upper-layer protocols.  The safest web site in the world is worthless
568c2ecf20Sopenharmony_ci   if most TCP implementations cannot transfer data from it.  It would
578c2ecf20Sopenharmony_ci   be far nicer to have all of the black holes fixed rather than fixing
588c2ecf20Sopenharmony_ci   all of the TCP implementations."
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci			   Golden words :-).
618c2ecf20Sopenharmony_ci		   */
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci			dst_negative_advice(sk);
648c2ecf20Sopenharmony_ci		}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci		retry_until = sysctl_dccp_retries2;
678c2ecf20Sopenharmony_ci		/*
688c2ecf20Sopenharmony_ci		 * FIXME: see tcp_write_timout and tcp_out_of_resources
698c2ecf20Sopenharmony_ci		 */
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	if (icsk->icsk_retransmits >= retry_until) {
738c2ecf20Sopenharmony_ci		/* Has it gone just too far? */
748c2ecf20Sopenharmony_ci		dccp_write_err(sk);
758c2ecf20Sopenharmony_ci		return 1;
768c2ecf20Sopenharmony_ci	}
778c2ecf20Sopenharmony_ci	return 0;
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci/*
818c2ecf20Sopenharmony_ci *	The DCCP retransmit timer.
828c2ecf20Sopenharmony_ci */
838c2ecf20Sopenharmony_cistatic void dccp_retransmit_timer(struct sock *sk)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	struct inet_connection_sock *icsk = inet_csk(sk);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	/*
888c2ecf20Sopenharmony_ci	 * More than 4MSL (8 minutes) has passed, a RESET(aborted) was
898c2ecf20Sopenharmony_ci	 * sent, no need to retransmit, this sock is dead.
908c2ecf20Sopenharmony_ci	 */
918c2ecf20Sopenharmony_ci	if (dccp_write_timeout(sk))
928c2ecf20Sopenharmony_ci		return;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	/*
958c2ecf20Sopenharmony_ci	 * We want to know the number of packets retransmitted, not the
968c2ecf20Sopenharmony_ci	 * total number of retransmissions of clones of original packets.
978c2ecf20Sopenharmony_ci	 */
988c2ecf20Sopenharmony_ci	if (icsk->icsk_retransmits == 0)
998c2ecf20Sopenharmony_ci		__DCCP_INC_STATS(DCCP_MIB_TIMEOUTS);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	if (dccp_retransmit_skb(sk) != 0) {
1028c2ecf20Sopenharmony_ci		/*
1038c2ecf20Sopenharmony_ci		 * Retransmission failed because of local congestion,
1048c2ecf20Sopenharmony_ci		 * do not backoff.
1058c2ecf20Sopenharmony_ci		 */
1068c2ecf20Sopenharmony_ci		if (--icsk->icsk_retransmits == 0)
1078c2ecf20Sopenharmony_ci			icsk->icsk_retransmits = 1;
1088c2ecf20Sopenharmony_ci		inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
1098c2ecf20Sopenharmony_ci					  min(icsk->icsk_rto,
1108c2ecf20Sopenharmony_ci					      TCP_RESOURCE_PROBE_INTERVAL),
1118c2ecf20Sopenharmony_ci					  DCCP_RTO_MAX);
1128c2ecf20Sopenharmony_ci		return;
1138c2ecf20Sopenharmony_ci	}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	icsk->icsk_backoff++;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
1188c2ecf20Sopenharmony_ci	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto,
1198c2ecf20Sopenharmony_ci				  DCCP_RTO_MAX);
1208c2ecf20Sopenharmony_ci	if (icsk->icsk_retransmits > sysctl_dccp_retries1)
1218c2ecf20Sopenharmony_ci		__sk_dst_reset(sk);
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistatic void dccp_write_timer(struct timer_list *t)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	struct inet_connection_sock *icsk =
1278c2ecf20Sopenharmony_ci			from_timer(icsk, t, icsk_retransmit_timer);
1288c2ecf20Sopenharmony_ci	struct sock *sk = &icsk->icsk_inet.sk;
1298c2ecf20Sopenharmony_ci	int event = 0;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	bh_lock_sock(sk);
1328c2ecf20Sopenharmony_ci	if (sock_owned_by_user(sk)) {
1338c2ecf20Sopenharmony_ci		/* Try again later */
1348c2ecf20Sopenharmony_ci		sk_reset_timer(sk, &icsk->icsk_retransmit_timer,
1358c2ecf20Sopenharmony_ci			       jiffies + (HZ / 20));
1368c2ecf20Sopenharmony_ci		goto out;
1378c2ecf20Sopenharmony_ci	}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	if (sk->sk_state == DCCP_CLOSED || !icsk->icsk_pending)
1408c2ecf20Sopenharmony_ci		goto out;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	if (time_after(icsk->icsk_timeout, jiffies)) {
1438c2ecf20Sopenharmony_ci		sk_reset_timer(sk, &icsk->icsk_retransmit_timer,
1448c2ecf20Sopenharmony_ci			       icsk->icsk_timeout);
1458c2ecf20Sopenharmony_ci		goto out;
1468c2ecf20Sopenharmony_ci	}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	event = icsk->icsk_pending;
1498c2ecf20Sopenharmony_ci	icsk->icsk_pending = 0;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	switch (event) {
1528c2ecf20Sopenharmony_ci	case ICSK_TIME_RETRANS:
1538c2ecf20Sopenharmony_ci		dccp_retransmit_timer(sk);
1548c2ecf20Sopenharmony_ci		break;
1558c2ecf20Sopenharmony_ci	}
1568c2ecf20Sopenharmony_ciout:
1578c2ecf20Sopenharmony_ci	bh_unlock_sock(sk);
1588c2ecf20Sopenharmony_ci	sock_put(sk);
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic void dccp_keepalive_timer(struct timer_list *t)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	struct sock *sk = from_timer(sk, t, sk_timer);
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	pr_err("dccp should not use a keepalive timer !\n");
1668c2ecf20Sopenharmony_ci	sock_put(sk);
1678c2ecf20Sopenharmony_ci}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci/* This is the same as tcp_delack_timer, sans prequeue & mem_reclaim stuff */
1708c2ecf20Sopenharmony_cistatic void dccp_delack_timer(struct timer_list *t)
1718c2ecf20Sopenharmony_ci{
1728c2ecf20Sopenharmony_ci	struct inet_connection_sock *icsk =
1738c2ecf20Sopenharmony_ci			from_timer(icsk, t, icsk_delack_timer);
1748c2ecf20Sopenharmony_ci	struct sock *sk = &icsk->icsk_inet.sk;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	bh_lock_sock(sk);
1778c2ecf20Sopenharmony_ci	if (sock_owned_by_user(sk)) {
1788c2ecf20Sopenharmony_ci		/* Try again later. */
1798c2ecf20Sopenharmony_ci		__NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED);
1808c2ecf20Sopenharmony_ci		sk_reset_timer(sk, &icsk->icsk_delack_timer,
1818c2ecf20Sopenharmony_ci			       jiffies + TCP_DELACK_MIN);
1828c2ecf20Sopenharmony_ci		goto out;
1838c2ecf20Sopenharmony_ci	}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	if (sk->sk_state == DCCP_CLOSED ||
1868c2ecf20Sopenharmony_ci	    !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
1878c2ecf20Sopenharmony_ci		goto out;
1888c2ecf20Sopenharmony_ci	if (time_after(icsk->icsk_ack.timeout, jiffies)) {
1898c2ecf20Sopenharmony_ci		sk_reset_timer(sk, &icsk->icsk_delack_timer,
1908c2ecf20Sopenharmony_ci			       icsk->icsk_ack.timeout);
1918c2ecf20Sopenharmony_ci		goto out;
1928c2ecf20Sopenharmony_ci	}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	if (inet_csk_ack_scheduled(sk)) {
1978c2ecf20Sopenharmony_ci		if (!inet_csk_in_pingpong_mode(sk)) {
1988c2ecf20Sopenharmony_ci			/* Delayed ACK missed: inflate ATO. */
1998c2ecf20Sopenharmony_ci			icsk->icsk_ack.ato = min(icsk->icsk_ack.ato << 1,
2008c2ecf20Sopenharmony_ci						 icsk->icsk_rto);
2018c2ecf20Sopenharmony_ci		} else {
2028c2ecf20Sopenharmony_ci			/* Delayed ACK missed: leave pingpong mode and
2038c2ecf20Sopenharmony_ci			 * deflate ATO.
2048c2ecf20Sopenharmony_ci			 */
2058c2ecf20Sopenharmony_ci			inet_csk_exit_pingpong_mode(sk);
2068c2ecf20Sopenharmony_ci			icsk->icsk_ack.ato = TCP_ATO_MIN;
2078c2ecf20Sopenharmony_ci		}
2088c2ecf20Sopenharmony_ci		dccp_send_ack(sk);
2098c2ecf20Sopenharmony_ci		__NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKS);
2108c2ecf20Sopenharmony_ci	}
2118c2ecf20Sopenharmony_ciout:
2128c2ecf20Sopenharmony_ci	bh_unlock_sock(sk);
2138c2ecf20Sopenharmony_ci	sock_put(sk);
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci/**
2178c2ecf20Sopenharmony_ci * dccp_write_xmitlet  -  Workhorse for CCID packet dequeueing interface
2188c2ecf20Sopenharmony_ci * @data: Socket to act on
2198c2ecf20Sopenharmony_ci *
2208c2ecf20Sopenharmony_ci * See the comments above %ccid_dequeueing_decision for supported modes.
2218c2ecf20Sopenharmony_ci */
2228c2ecf20Sopenharmony_cistatic void dccp_write_xmitlet(unsigned long data)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	struct sock *sk = (struct sock *)data;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	bh_lock_sock(sk);
2278c2ecf20Sopenharmony_ci	if (sock_owned_by_user(sk))
2288c2ecf20Sopenharmony_ci		sk_reset_timer(sk, &dccp_sk(sk)->dccps_xmit_timer, jiffies + 1);
2298c2ecf20Sopenharmony_ci	else
2308c2ecf20Sopenharmony_ci		dccp_write_xmit(sk);
2318c2ecf20Sopenharmony_ci	bh_unlock_sock(sk);
2328c2ecf20Sopenharmony_ci	sock_put(sk);
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic void dccp_write_xmit_timer(struct timer_list *t)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci	struct dccp_sock *dp = from_timer(dp, t, dccps_xmit_timer);
2388c2ecf20Sopenharmony_ci	struct sock *sk = &dp->dccps_inet_connection.icsk_inet.sk;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	dccp_write_xmitlet((unsigned long)sk);
2418c2ecf20Sopenharmony_ci}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_civoid dccp_init_xmit_timers(struct sock *sk)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	struct dccp_sock *dp = dccp_sk(sk);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	tasklet_init(&dp->dccps_xmitlet, dccp_write_xmitlet, (unsigned long)sk);
2488c2ecf20Sopenharmony_ci	timer_setup(&dp->dccps_xmit_timer, dccp_write_xmit_timer, 0);
2498c2ecf20Sopenharmony_ci	inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer,
2508c2ecf20Sopenharmony_ci				  &dccp_keepalive_timer);
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistatic ktime_t dccp_timestamp_seed;
2548c2ecf20Sopenharmony_ci/**
2558c2ecf20Sopenharmony_ci * dccp_timestamp  -  10s of microseconds time source
2568c2ecf20Sopenharmony_ci * Returns the number of 10s of microseconds since loading DCCP. This is native
2578c2ecf20Sopenharmony_ci * DCCP time difference format (RFC 4340, sec. 13).
2588c2ecf20Sopenharmony_ci * Please note: This will wrap around about circa every 11.9 hours.
2598c2ecf20Sopenharmony_ci */
2608c2ecf20Sopenharmony_ciu32 dccp_timestamp(void)
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci	u64 delta = (u64)ktime_us_delta(ktime_get_real(), dccp_timestamp_seed);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	do_div(delta, 10);
2658c2ecf20Sopenharmony_ci	return delta;
2668c2ecf20Sopenharmony_ci}
2678c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dccp_timestamp);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_civoid __init dccp_timestamping_init(void)
2708c2ecf20Sopenharmony_ci{
2718c2ecf20Sopenharmony_ci	dccp_timestamp_seed = ktime_get_real();
2728c2ecf20Sopenharmony_ci}
273