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