Blame view
net/ipv4/tcp_hybla.c
4.89 KB
835b3f0c0 [TCP]: Add TCP Hy... |
1 2 3 4 5 6 7 8 9 10 11 |
/* * TCP HYBLA * * TCP-HYBLA Congestion control algorithm, based on: * C.Caini, R.Firrincieli, "TCP-Hybla: A TCP Enhancement * for Heterogeneous Networks", * International Journal on satellite Communications, * September 2004 * Daniele Lacamera * root at danielinux.net */ |
835b3f0c0 [TCP]: Add TCP Hy... |
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#include <linux/module.h> #include <net/tcp.h> /* Tcp Hybla structure. */ struct hybla { u8 hybla_en; u32 snd_cwnd_cents; /* Keeps increment values when it is <1, <<7 */ u32 rho; /* Rho parameter, integer part */ u32 rho2; /* Rho * Rho, integer part */ u32 rho_3ls; /* Rho parameter, <<3 */ u32 rho2_7ls; /* Rho^2, <<7 */ u32 minrtt; /* Minimum smoothed round trip time value seen */ }; /* Hybla reference round trip time (default= 1/40 sec = 25 ms), expressed in jiffies */ static int rtt0 = 25; module_param(rtt0, int, 0644); MODULE_PARM_DESC(rtt0, "reference rout trip time (ms)"); /* This is called to refresh values for hybla parameters */ |
6687e988d [ICSK]: Move TCP ... |
34 |
static inline void hybla_recalc_param (struct sock *sk) |
835b3f0c0 [TCP]: Add TCP Hy... |
35 |
{ |
6687e988d [ICSK]: Move TCP ... |
36 |
struct hybla *ca = inet_csk_ca(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
37 |
|
6687e988d [ICSK]: Move TCP ... |
38 |
ca->rho_3ls = max_t(u32, tcp_sk(sk)->srtt / msecs_to_jiffies(rtt0), 8); |
835b3f0c0 [TCP]: Add TCP Hy... |
39 40 41 42 |
ca->rho = ca->rho_3ls >> 3; ca->rho2_7ls = (ca->rho_3ls * ca->rho_3ls) << 1; ca->rho2 = ca->rho2_7ls >>7; } |
6687e988d [ICSK]: Move TCP ... |
43 |
static void hybla_init(struct sock *sk) |
835b3f0c0 [TCP]: Add TCP Hy... |
44 |
{ |
6687e988d [ICSK]: Move TCP ... |
45 46 |
struct tcp_sock *tp = tcp_sk(sk); struct hybla *ca = inet_csk_ca(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
47 48 49 50 51 52 53 54 55 56 57 |
ca->rho = 0; ca->rho2 = 0; ca->rho_3ls = 0; ca->rho2_7ls = 0; ca->snd_cwnd_cents = 0; ca->hybla_en = 1; tp->snd_cwnd = 2; tp->snd_cwnd_clamp = 65535; /* 1st Rho measurement based on initial srtt */ |
6687e988d [ICSK]: Move TCP ... |
58 |
hybla_recalc_param(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
59 60 61 62 63 |
/* set minimum rtt as this is the 1st ever seen */ ca->minrtt = tp->srtt; tp->snd_cwnd = ca->rho; } |
6687e988d [ICSK]: Move TCP ... |
64 |
static void hybla_state(struct sock *sk, u8 ca_state) |
835b3f0c0 [TCP]: Add TCP Hy... |
65 |
{ |
6687e988d [ICSK]: Move TCP ... |
66 |
struct hybla *ca = inet_csk_ca(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
ca->hybla_en = (ca_state == TCP_CA_Open); } static inline u32 hybla_fraction(u32 odds) { static const u32 fractions[] = { 128, 139, 152, 165, 181, 197, 215, 234, }; return (odds < ARRAY_SIZE(fractions)) ? fractions[odds] : 128; } /* TCP Hybla main routine. * This is the algorithm behavior: * o Recalc Hybla parameters if min_rtt has changed * o Give cwnd a new value based on the model proposed * o remember increments <1 */ |
c3a05c605 [TCP]: Cong.ctrl ... |
85 |
static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 in_flight) |
835b3f0c0 [TCP]: Add TCP Hy... |
86 |
{ |
6687e988d [ICSK]: Move TCP ... |
87 88 |
struct tcp_sock *tp = tcp_sk(sk); struct hybla *ca = inet_csk_ca(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
89 90 91 92 93 |
u32 increment, odd, rho_fractions; int is_slowstart = 0; /* Recalculate rho only if this srtt is the lowest */ if (tp->srtt < ca->minrtt){ |
6687e988d [ICSK]: Move TCP ... |
94 |
hybla_recalc_param(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
95 96 |
ca->minrtt = tp->srtt; } |
f4805eded [TCP]: fix conges... |
97 98 |
if (!tcp_is_cwnd_limited(sk, in_flight)) return; |
ab59859de net: fix returnin... |
99 100 101 102 |
if (!ca->hybla_en) { tcp_reno_cong_avoid(sk, ack, in_flight); return; } |
835b3f0c0 [TCP]: Add TCP Hy... |
103 |
|
835b3f0c0 [TCP]: Add TCP Hy... |
104 |
if (ca->rho == 0) |
6687e988d [ICSK]: Move TCP ... |
105 |
hybla_recalc_param(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
rho_fractions = ca->rho_3ls - (ca->rho << 3); if (tp->snd_cwnd < tp->snd_ssthresh) { /* * slow start * INC = 2^RHO - 1 * This is done by splitting the rho parameter * into 2 parts: an integer part and a fraction part. * Inrement<<7 is estimated by doing: * [2^(int+fract)]<<7 * that is equal to: * (2^int) * [(2^fract) <<7] * 2^int is straightly computed as 1<<int, * while we will use hybla_slowstart_fraction_increment() to * calculate 2^fract in a <<7 value. */ is_slowstart = 1; |
edafe5024 TCP: tcp_hybla: F... |
124 125 |
increment = ((1 << min(ca->rho, 16U)) * hybla_fraction(rho_fractions)) - 128; |
835b3f0c0 [TCP]: Add TCP Hy... |
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
} else { /* * congestion avoidance * INC = RHO^2 / W * as long as increment is estimated as (rho<<7)/window * it already is <<7 and we can easily count its fractions. */ increment = ca->rho2_7ls / tp->snd_cwnd; if (increment < 128) tp->snd_cwnd_cnt++; } odd = increment % 128; tp->snd_cwnd += increment >> 7; ca->snd_cwnd_cents += odd; /* check when fractions goes >=128 and increase cwnd by 1. */ |
2de979bd7 [TCP]: whitespace... |
143 |
while (ca->snd_cwnd_cents >= 128) { |
835b3f0c0 [TCP]: Add TCP Hy... |
144 145 146 147 |
tp->snd_cwnd++; ca->snd_cwnd_cents -= 128; tp->snd_cwnd_cnt = 0; } |
9d2c27e17 tcp: Fix tcp_hybl... |
148 149 150 151 152 |
/* check when cwnd has not been incremented for a while */ if (increment == 0 && odd == 0 && tp->snd_cwnd_cnt >= tp->snd_cwnd) { tp->snd_cwnd++; tp->snd_cwnd_cnt = 0; } |
835b3f0c0 [TCP]: Add TCP Hy... |
153 154 155 156 157 158 |
/* clamp down slowstart cwnd to ssthresh value. */ if (is_slowstart) tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp); } |
a252bebe2 tcp: mark tcp_con... |
159 |
static struct tcp_congestion_ops tcp_hybla __read_mostly = { |
835b3f0c0 [TCP]: Add TCP Hy... |
160 161 162 163 164 165 166 167 168 169 170 171 |
.init = hybla_init, .ssthresh = tcp_reno_ssthresh, .min_cwnd = tcp_reno_min_cwnd, .cong_avoid = hybla_cong_avoid, .set_state = hybla_state, .owner = THIS_MODULE, .name = "hybla" }; static int __init hybla_register(void) { |
74975d40b [TCP] Congestion ... |
172 |
BUILD_BUG_ON(sizeof(struct hybla) > ICSK_CA_PRIV_SIZE); |
835b3f0c0 [TCP]: Add TCP Hy... |
173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
return tcp_register_congestion_control(&tcp_hybla); } static void __exit hybla_unregister(void) { tcp_unregister_congestion_control(&tcp_hybla); } module_init(hybla_register); module_exit(hybla_unregister); MODULE_AUTHOR("Daniele Lacamera"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("TCP Hybla"); |