1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2024 Huawei Device Co., Ltd.
4  *
5  * Network and Application-driven Transport Augmentation (NATA).
6  * Authors: yangyanjun
7  */
8 #if defined(CONFIG_TCP_NATA_URC) || defined(CONFIG_TCP_NATA_STL)
9 #include <net/inet_sock.h>
10 #include <net/sock.h>
11 #include <net/nata.h>
12 #include <net/tcp.h>
13 
14 #define NATA_THIN_STREAM 4
nata_thin_stream_check(struct sock *sk)15 bool nata_thin_stream_check(struct sock *sk)
16 {
17 	struct tcp_sock *tp = tcp_sk(sk);
18 	/* The server side focuses on syn-ack retransmission,
19 	 * and the client side focuses on syn retransmission.
20 	 */
21 	if ((sk->sk_state == TCP_ESTABLISHED &&
22 	    tp->packets_out <= NATA_THIN_STREAM) ||
23 	    sk->sk_state == TCP_SYN_SENT)
24 		return true;
25 	return false;
26 }
27 
28 #ifdef CONFIG_TCP_NATA_URC
tcp_set_nata_urc(struct sock *sk, sockptr_t optval, int optlen)29 int tcp_set_nata_urc(struct sock *sk, sockptr_t optval, int optlen)
30 {
31 	int err = -EINVAL;
32 	struct tcp_nata_urc opt = {};
33 	struct inet_connection_sock *icsk = inet_csk(sk);
34 
35 	if (optlen != sizeof(struct tcp_nata_urc))
36 		return err;
37 
38 	if (copy_from_sockptr(&opt, optval, optlen))
39 		return err;
40 
41 	if (!opt.nata_urc_enabled) {
42 		icsk->nata_retries_enabled = opt.nata_urc_enabled;
43 		icsk->nata_retries_type = NATA_NA;
44 		icsk->icsk_syn_retries = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_syn_retries);
45 		icsk->nata_data_retries = 0;
46 		icsk->nata_syn_rto = TCP_TIMEOUT_INIT;
47 		icsk->nata_data_rto = TCP_TIMEOUT_INIT;
48 		return 0;
49 	}
50 
51 	if (opt.nata_rto_ms < NATA_URC_RTO_MS_MIN ||
52 		opt.nata_rto_ms > NATA_URC_RTO_MS_MAX )
53 		return err;
54 
55 	if (opt.nata_data_retries > NATA_DATA_RETRIES_MAX ||
56 		opt.nata_syn_retries > NATA_SYN_RETRIES_MAX)
57 		return err;
58 
59 	icsk->nata_retries_enabled = opt.nata_urc_enabled;
60 	icsk->nata_retries_type = NATA_URC;
61 	icsk->icsk_syn_retries = opt.nata_syn_retries;
62 	icsk->nata_data_retries = opt.nata_data_retries;
63 	icsk->nata_data_rto = opt.nata_rto_ms * HZ / NATA_URC_RTO_MS_TO_HZ;
64 	icsk->nata_syn_rto = icsk->nata_data_rto;
65 	return 0;
66 }
67 #endif /* CONFIG_TCP_NATA_URC */
68 
69 #ifdef CONFIG_TCP_NATA_STL
tcp_set_nata_stl(struct sock *sk, sockptr_t optval, int optlen)70 int tcp_set_nata_stl(struct sock *sk, sockptr_t optval, int optlen)
71 {
72 	int err = -EINVAL;
73 	struct tcp_nata_stl opt = {};
74 	struct inet_connection_sock *icsk = inet_csk(sk);
75 
76 	if (optlen != sizeof(struct tcp_nata_stl))
77 		return err;
78 
79 	if (copy_from_sockptr(&opt, optval, optlen))
80 		return err;
81 
82 	if (!opt.nata_stl_enabled) {
83 		icsk->nata_retries_enabled = opt.nata_stl_enabled;
84 		icsk->nata_retries_type = NATA_NA;
85 		icsk->icsk_syn_retries = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_syn_retries);
86 		icsk->nata_data_retries = 0;
87 		icsk->nata_syn_rto = TCP_TIMEOUT_INIT;
88 		icsk->nata_data_rto = TCP_TIMEOUT_INIT;
89 		return 0;
90 	}
91 
92 	if ((opt.nata_syn_rto_ms < NATA_STL_SYN_RTO_MS_MIN ||
93 		opt.nata_syn_rto_ms > NATA_STL_RTO_MS_MAX ||
94 		opt.nata_data_rto_ms < NATA_STL_DATA_RTO_MS_MIN ||
95 		opt.nata_data_rto_ms > NATA_STL_RTO_MS_MAX))
96 		return err;
97 
98 	if (opt.nata_data_retries > NATA_DATA_RETRIES_MAX ||
99 		opt.nata_syn_retries > NATA_SYN_RETRIES_MAX)
100 		return err;
101 
102 	icsk->nata_retries_enabled = opt.nata_stl_enabled;
103 	icsk->nata_retries_type = NATA_STL;
104 	icsk->icsk_syn_retries = opt.nata_syn_retries;
105 	icsk->nata_data_retries = opt.nata_data_retries;
106 	icsk->nata_syn_rto = opt.nata_syn_rto_ms * HZ / NATA_STL_RTO_MS_TO_HZ;
107 	icsk->nata_data_rto = opt.nata_data_rto_ms * HZ / NATA_STL_RTO_MS_TO_HZ;
108 	return 0;
109 }
110 #endif /* CONFIG_TCP_NATA_STL */
111 #endif