18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Network and Application-driven Transport Augmentation (NATA). 68c2ecf20Sopenharmony_ci * Authors: yangyanjun 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#if defined(CONFIG_TCP_NATA_URC) || defined(CONFIG_TCP_NATA_STL) 98c2ecf20Sopenharmony_ci#include <net/inet_sock.h> 108c2ecf20Sopenharmony_ci#include <net/sock.h> 118c2ecf20Sopenharmony_ci#include <net/nata.h> 128c2ecf20Sopenharmony_ci#include <net/tcp.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define NATA_THIN_STREAM 4 158c2ecf20Sopenharmony_cibool nata_thin_stream_check(struct sock *sk) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci struct tcp_sock *tp = tcp_sk(sk); 188c2ecf20Sopenharmony_ci /* The server side focuses on syn-ack retransmission, 198c2ecf20Sopenharmony_ci * and the client side focuses on syn retransmission. 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_ci if ((sk->sk_state == TCP_ESTABLISHED && 228c2ecf20Sopenharmony_ci tp->packets_out <= NATA_THIN_STREAM) || 238c2ecf20Sopenharmony_ci sk->sk_state == TCP_SYN_SENT) 248c2ecf20Sopenharmony_ci return true; 258c2ecf20Sopenharmony_ci return false; 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_NATA_URC 298c2ecf20Sopenharmony_ciint tcp_set_nata_urc(struct sock *sk, sockptr_t optval, int optlen) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci int err = -EINVAL; 328c2ecf20Sopenharmony_ci struct tcp_nata_urc opt = {}; 338c2ecf20Sopenharmony_ci struct inet_connection_sock *icsk = inet_csk(sk); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci if (optlen != sizeof(struct tcp_nata_urc)) 368c2ecf20Sopenharmony_ci return err; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci if (copy_from_sockptr(&opt, optval, optlen)) 398c2ecf20Sopenharmony_ci return err; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci if (!opt.nata_urc_enabled) { 428c2ecf20Sopenharmony_ci icsk->nata_retries_enabled = opt.nata_urc_enabled; 438c2ecf20Sopenharmony_ci icsk->nata_retries_type = NATA_NA; 448c2ecf20Sopenharmony_ci icsk->icsk_syn_retries = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_syn_retries); 458c2ecf20Sopenharmony_ci icsk->nata_data_retries = 0; 468c2ecf20Sopenharmony_ci icsk->nata_syn_rto = TCP_TIMEOUT_INIT; 478c2ecf20Sopenharmony_ci icsk->nata_data_rto = TCP_TIMEOUT_INIT; 488c2ecf20Sopenharmony_ci return 0; 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci if (opt.nata_rto_ms < NATA_URC_RTO_MS_MIN || 528c2ecf20Sopenharmony_ci opt.nata_rto_ms > NATA_URC_RTO_MS_MAX ) 538c2ecf20Sopenharmony_ci return err; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (opt.nata_data_retries > NATA_DATA_RETRIES_MAX || 568c2ecf20Sopenharmony_ci opt.nata_syn_retries > NATA_SYN_RETRIES_MAX) 578c2ecf20Sopenharmony_ci return err; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci icsk->nata_retries_enabled = opt.nata_urc_enabled; 608c2ecf20Sopenharmony_ci icsk->nata_retries_type = NATA_URC; 618c2ecf20Sopenharmony_ci icsk->icsk_syn_retries = opt.nata_syn_retries; 628c2ecf20Sopenharmony_ci icsk->nata_data_retries = opt.nata_data_retries; 638c2ecf20Sopenharmony_ci icsk->nata_data_rto = opt.nata_rto_ms * HZ / NATA_URC_RTO_MS_TO_HZ; 648c2ecf20Sopenharmony_ci icsk->nata_syn_rto = icsk->nata_data_rto; 658c2ecf20Sopenharmony_ci return 0; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci#endif /* CONFIG_TCP_NATA_URC */ 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_NATA_STL 708c2ecf20Sopenharmony_ciint tcp_set_nata_stl(struct sock *sk, sockptr_t optval, int optlen) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci int err = -EINVAL; 738c2ecf20Sopenharmony_ci struct tcp_nata_stl opt = {}; 748c2ecf20Sopenharmony_ci struct inet_connection_sock *icsk = inet_csk(sk); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if (optlen != sizeof(struct tcp_nata_stl)) 778c2ecf20Sopenharmony_ci return err; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (copy_from_sockptr(&opt, optval, optlen)) 808c2ecf20Sopenharmony_ci return err; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci if (!opt.nata_stl_enabled) { 838c2ecf20Sopenharmony_ci icsk->nata_retries_enabled = opt.nata_stl_enabled; 848c2ecf20Sopenharmony_ci icsk->nata_retries_type = NATA_NA; 858c2ecf20Sopenharmony_ci icsk->icsk_syn_retries = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_syn_retries); 868c2ecf20Sopenharmony_ci icsk->nata_data_retries = 0; 878c2ecf20Sopenharmony_ci icsk->nata_syn_rto = TCP_TIMEOUT_INIT; 888c2ecf20Sopenharmony_ci icsk->nata_data_rto = TCP_TIMEOUT_INIT; 898c2ecf20Sopenharmony_ci return 0; 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if ((opt.nata_syn_rto_ms < NATA_STL_SYN_RTO_MS_MIN || 938c2ecf20Sopenharmony_ci opt.nata_syn_rto_ms > NATA_STL_RTO_MS_MAX || 948c2ecf20Sopenharmony_ci opt.nata_data_rto_ms < NATA_STL_DATA_RTO_MS_MIN || 958c2ecf20Sopenharmony_ci opt.nata_data_rto_ms > NATA_STL_RTO_MS_MAX)) 968c2ecf20Sopenharmony_ci return err; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (opt.nata_data_retries > NATA_DATA_RETRIES_MAX || 998c2ecf20Sopenharmony_ci opt.nata_syn_retries > NATA_SYN_RETRIES_MAX) 1008c2ecf20Sopenharmony_ci return err; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci icsk->nata_retries_enabled = opt.nata_stl_enabled; 1038c2ecf20Sopenharmony_ci icsk->nata_retries_type = NATA_STL; 1048c2ecf20Sopenharmony_ci icsk->icsk_syn_retries = opt.nata_syn_retries; 1058c2ecf20Sopenharmony_ci icsk->nata_data_retries = opt.nata_data_retries; 1068c2ecf20Sopenharmony_ci icsk->nata_syn_rto = opt.nata_syn_rto_ms * HZ / NATA_STL_RTO_MS_TO_HZ; 1078c2ecf20Sopenharmony_ci icsk->nata_data_rto = opt.nata_data_rto_ms * HZ / NATA_STL_RTO_MS_TO_HZ; 1088c2ecf20Sopenharmony_ci return 0; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci#endif /* CONFIG_TCP_NATA_STL */ 1118c2ecf20Sopenharmony_ci#endif