Blame view
net/ipv4/tcp_hybla.c
4.85 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 |
#include <linux/module.h> #include <net/tcp.h> /* Tcp Hybla structure. */ struct hybla { |
a2a385d62 tcp: bool convers... |
17 |
bool hybla_en; |
835b3f0c0 [TCP]: Add TCP Hy... |
18 19 20 21 22 |
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 */ |
740b0f184 tcp: switch rtt e... |
23 |
u32 minrtt_us; /* Minimum smoothed round trip time value seen */ |
835b3f0c0 [TCP]: Add TCP Hy... |
24 |
}; |
a2a385d62 tcp: bool convers... |
25 |
/* Hybla reference round trip time (default= 1/40 sec = 25 ms), in ms */ |
835b3f0c0 [TCP]: Add TCP Hy... |
26 27 28 |
static int rtt0 = 25; module_param(rtt0, int, 0644); MODULE_PARM_DESC(rtt0, "reference rout trip time (ms)"); |
835b3f0c0 [TCP]: Add TCP Hy... |
29 |
/* This is called to refresh values for hybla parameters */ |
6687e988d [ICSK]: Move TCP ... |
30 |
static inline void hybla_recalc_param (struct sock *sk) |
835b3f0c0 [TCP]: Add TCP Hy... |
31 |
{ |
6687e988d [ICSK]: Move TCP ... |
32 |
struct hybla *ca = inet_csk_ca(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
33 |
|
740b0f184 tcp: switch rtt e... |
34 35 36 |
ca->rho_3ls = max_t(u32, tcp_sk(sk)->srtt_us / (rtt0 * USEC_PER_MSEC), 8U); |
835b3f0c0 [TCP]: Add TCP Hy... |
37 38 |
ca->rho = ca->rho_3ls >> 3; ca->rho2_7ls = (ca->rho_3ls * ca->rho_3ls) << 1; |
a2a385d62 tcp: bool convers... |
39 |
ca->rho2 = ca->rho2_7ls >> 7; |
835b3f0c0 [TCP]: Add TCP Hy... |
40 |
} |
6687e988d [ICSK]: Move TCP ... |
41 |
static void hybla_init(struct sock *sk) |
835b3f0c0 [TCP]: Add TCP Hy... |
42 |
{ |
6687e988d [ICSK]: Move TCP ... |
43 44 |
struct tcp_sock *tp = tcp_sk(sk); struct hybla *ca = inet_csk_ca(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
45 46 47 48 49 50 |
ca->rho = 0; ca->rho2 = 0; ca->rho_3ls = 0; ca->rho2_7ls = 0; ca->snd_cwnd_cents = 0; |
a2a385d62 tcp: bool convers... |
51 |
ca->hybla_en = true; |
835b3f0c0 [TCP]: Add TCP Hy... |
52 53 54 55 |
tp->snd_cwnd = 2; tp->snd_cwnd_clamp = 65535; /* 1st Rho measurement based on initial srtt */ |
6687e988d [ICSK]: Move TCP ... |
56 |
hybla_recalc_param(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
57 58 |
/* set minimum rtt as this is the 1st ever seen */ |
740b0f184 tcp: switch rtt e... |
59 |
ca->minrtt_us = tp->srtt_us; |
835b3f0c0 [TCP]: Add TCP Hy... |
60 61 |
tp->snd_cwnd = ca->rho; } |
6687e988d [ICSK]: Move TCP ... |
62 |
static void hybla_state(struct sock *sk, u8 ca_state) |
835b3f0c0 [TCP]: Add TCP Hy... |
63 |
{ |
6687e988d [ICSK]: Move TCP ... |
64 |
struct hybla *ca = inet_csk_ca(sk); |
a2a385d62 tcp: bool convers... |
65 |
|
835b3f0c0 [TCP]: Add TCP Hy... |
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
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 */ |
249015515 tcp: remove in_fl... |
84 |
static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 acked) |
835b3f0c0 [TCP]: Add TCP Hy... |
85 |
{ |
6687e988d [ICSK]: Move TCP ... |
86 87 |
struct tcp_sock *tp = tcp_sk(sk); struct hybla *ca = inet_csk_ca(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
88 89 90 91 |
u32 increment, odd, rho_fractions; int is_slowstart = 0; /* Recalculate rho only if this srtt is the lowest */ |
740b0f184 tcp: switch rtt e... |
92 |
if (tp->srtt_us < ca->minrtt_us) { |
6687e988d [ICSK]: Move TCP ... |
93 |
hybla_recalc_param(sk); |
740b0f184 tcp: switch rtt e... |
94 |
ca->minrtt_us = tp->srtt_us; |
835b3f0c0 [TCP]: Add TCP Hy... |
95 |
} |
249015515 tcp: remove in_fl... |
96 |
if (!tcp_is_cwnd_limited(sk)) |
f4805eded [TCP]: fix conges... |
97 |
return; |
ab59859de net: fix returnin... |
98 |
if (!ca->hybla_en) { |
249015515 tcp: remove in_fl... |
99 |
tcp_reno_cong_avoid(sk, ack, acked); |
ab59859de net: fix returnin... |
100 101 |
return; } |
835b3f0c0 [TCP]: Add TCP Hy... |
102 |
|
835b3f0c0 [TCP]: Add TCP Hy... |
103 |
if (ca->rho == 0) |
6687e988d [ICSK]: Move TCP ... |
104 |
hybla_recalc_param(sk); |
835b3f0c0 [TCP]: Add TCP Hy... |
105 106 |
rho_fractions = ca->rho_3ls - (ca->rho << 3); |
76174004a tcp: do not slow ... |
107 |
if (tcp_in_slow_start(tp)) { |
835b3f0c0 [TCP]: Add TCP Hy... |
108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
/* * 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... |
122 123 |
increment = ((1 << min(ca->rho, 16U)) * hybla_fraction(rho_fractions)) - 128; |
835b3f0c0 [TCP]: Add TCP Hy... |
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
} 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... |
141 |
while (ca->snd_cwnd_cents >= 128) { |
835b3f0c0 [TCP]: Add TCP Hy... |
142 143 144 145 |
tp->snd_cwnd++; ca->snd_cwnd_cents -= 128; tp->snd_cwnd_cnt = 0; } |
9d2c27e17 tcp: Fix tcp_hybl... |
146 147 148 149 150 |
/* 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... |
151 152 153 154 155 156 |
/* 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... |
157 |
static struct tcp_congestion_ops tcp_hybla __read_mostly = { |
835b3f0c0 [TCP]: Add TCP Hy... |
158 159 |
.init = hybla_init, .ssthresh = tcp_reno_ssthresh, |
835b3f0c0 [TCP]: Add TCP Hy... |
160 161 162 163 164 165 166 167 168 |
.cong_avoid = hybla_cong_avoid, .set_state = hybla_state, .owner = THIS_MODULE, .name = "hybla" }; static int __init hybla_register(void) { |
74975d40b [TCP] Congestion ... |
169 |
BUILD_BUG_ON(sizeof(struct hybla) > ICSK_CA_PRIV_SIZE); |
835b3f0c0 [TCP]: Add TCP Hy... |
170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
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"); |