blob: bbceced247fa9bcbb3f6cb89e207007464830a9c [file] [log] [blame]
/*
* TCP Transonic: a congestion controller that simply activates the TCP
* layer's built in fixed-rate congestion control tweaks.
*
* Only use this with fixed-rate streams that won't try to saturate the
* network, and only use it on a LAN. It would be very rude to use this
* on the open Internet (and it also probably wouldn't work).
*/
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/math64.h>
#include <net/tcp.h>
static void transonic_init(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
tp->is_rate_controlled = 1;
tp->is_aggressive_rto = 1;
}
static void transonic_cong_avoid(struct sock *sk, u32 ack, u32 acked)
{
}
static u32 transonic_recalc_ssthresh(struct sock *sk)
{
return 0;
}
static bool transonic_rate_control(struct sock *sk, unsigned int current_mss)
{
static DEFINE_RATELIMIT_STATE(transonic_rate, 2 * HZ, 1);
struct tcp_sock *tp = tcp_sk(sk);
u64 rate = 50*1000*1000/8; // max allowed streaming rate in bytes/sec
u32 agg_time_us = 25*1000, min_rtt;
if (!tp->is_rate_controlled)
return false;
/* Goal: cwnd of at least 2 aggregates. */
min_rtt = max_t(u32, 2 * agg_time_us, tcp_min_rtt(tp));
tp->snd_cwnd = DIV_ROUND_UP_ULL(2 * rate * min_rtt,
USEC_PER_SEC * current_mss);
/* avoid cwnd=1, just in case. */
tp->snd_cwnd = max(tp->snd_cwnd, 2U);
return true;
}
static struct tcp_congestion_ops transonic __read_mostly = {
.init = transonic_init,
.cong_avoid = transonic_cong_avoid,
.ssthresh = transonic_recalc_ssthresh,
.rate_control = transonic_rate_control,
.owner = THIS_MODULE,
.name = "transonic",
};
static int __init transonic_register(void)
{
return tcp_register_congestion_control(&transonic);
}
static void __exit transonic_unregister(void)
{
tcp_unregister_congestion_control(&transonic);
}
module_init(transonic_register);
module_exit(transonic_unregister);
MODULE_AUTHOR("Avery Pennarun");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Transonic TCP");
MODULE_VERSION("0.5");