162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Tom Kelly's Scalable TCP 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * See http://www.deneholme.net/tom/scalable/ 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * John Heffner <jheffner@sc.edu> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <net/tcp.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* These factors derived from the recommended values in the aer: 1362306a36Sopenharmony_ci * .01 and 7/8. 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_ci#define TCP_SCALABLE_AI_CNT 100U 1662306a36Sopenharmony_ci#define TCP_SCALABLE_MD_SCALE 3 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 acked) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci struct tcp_sock *tp = tcp_sk(sk); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci if (!tcp_is_cwnd_limited(sk)) 2362306a36Sopenharmony_ci return; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci if (tcp_in_slow_start(tp)) { 2662306a36Sopenharmony_ci acked = tcp_slow_start(tp, acked); 2762306a36Sopenharmony_ci if (!acked) 2862306a36Sopenharmony_ci return; 2962306a36Sopenharmony_ci } 3062306a36Sopenharmony_ci tcp_cong_avoid_ai(tp, min(tcp_snd_cwnd(tp), TCP_SCALABLE_AI_CNT), 3162306a36Sopenharmony_ci acked); 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic u32 tcp_scalable_ssthresh(struct sock *sk) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci const struct tcp_sock *tp = tcp_sk(sk); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci return max(tcp_snd_cwnd(tp) - (tcp_snd_cwnd(tp)>>TCP_SCALABLE_MD_SCALE), 2U); 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic struct tcp_congestion_ops tcp_scalable __read_mostly = { 4262306a36Sopenharmony_ci .ssthresh = tcp_scalable_ssthresh, 4362306a36Sopenharmony_ci .undo_cwnd = tcp_reno_undo_cwnd, 4462306a36Sopenharmony_ci .cong_avoid = tcp_scalable_cong_avoid, 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci .owner = THIS_MODULE, 4762306a36Sopenharmony_ci .name = "scalable", 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic int __init tcp_scalable_register(void) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci return tcp_register_congestion_control(&tcp_scalable); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic void __exit tcp_scalable_unregister(void) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci tcp_unregister_congestion_control(&tcp_scalable); 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cimodule_init(tcp_scalable_register); 6162306a36Sopenharmony_cimodule_exit(tcp_scalable_unregister); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ciMODULE_AUTHOR("John Heffner"); 6462306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 6562306a36Sopenharmony_ciMODULE_DESCRIPTION("Scalable TCP"); 66