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