Blame view
net/ipv4/tcp_cong.c
11.5 KB
457c89965 treewide: Add SPD... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
317a76f9a [TCP]: Add plugga... |
2 |
/* |
b92022f3e tcp: spelling s/p... |
3 |
* Pluggable TCP congestion control support and newReno |
317a76f9a [TCP]: Add plugga... |
4 |
* congestion control. |
02582e9bc treewide: fix typ... |
5 |
* Based on ideas from I/O scheduler support and Web100. |
317a76f9a [TCP]: Add plugga... |
6 7 8 |
* * Copyright (C) 2005 Stephen Hemminger <shemminger@osdl.org> */ |
afd465030 net: ipv4: Standa... |
9 |
#define pr_fmt(fmt) "TCP: " fmt |
317a76f9a [TCP]: Add plugga... |
10 11 12 13 |
#include <linux/module.h> #include <linux/mm.h> #include <linux/types.h> #include <linux/list.h> |
5a0e3ad6a include cleanup: ... |
14 |
#include <linux/gfp.h> |
c5c6a8ab4 net: tcp: add key... |
15 |
#include <linux/jhash.h> |
317a76f9a [TCP]: Add plugga... |
16 17 18 19 20 21 |
#include <net/tcp.h> static DEFINE_SPINLOCK(tcp_cong_list_lock); static LIST_HEAD(tcp_cong_list); /* Simple linear search, don't expect many entries! */ |
0baf26b0f bpf: tcp: Support... |
22 |
struct tcp_congestion_ops *tcp_ca_find(const char *name) |
317a76f9a [TCP]: Add plugga... |
23 24 |
{ struct tcp_congestion_ops *e; |
5f8ef48d2 [TCP]: Allow choo... |
25 |
list_for_each_entry_rcu(e, &tcp_cong_list, list) { |
317a76f9a [TCP]: Add plugga... |
26 27 28 29 30 31 |
if (strcmp(e->name, name) == 0) return e; } return NULL; } |
c5c6a8ab4 net: tcp: add key... |
32 |
/* Must be called with rcu lock held */ |
6670e1524 tcp: Namespace-if... |
33 34 |
static struct tcp_congestion_ops *tcp_ca_find_autoload(struct net *net, const char *name) |
c5c6a8ab4 net: tcp: add key... |
35 |
{ |
6670e1524 tcp: Namespace-if... |
36 |
struct tcp_congestion_ops *ca = tcp_ca_find(name); |
c5c6a8ab4 net: tcp: add key... |
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
#ifdef CONFIG_MODULES if (!ca && capable(CAP_NET_ADMIN)) { rcu_read_unlock(); request_module("tcp_%s", name); rcu_read_lock(); ca = tcp_ca_find(name); } #endif return ca; } /* Simple linear search, not much in here. */ struct tcp_congestion_ops *tcp_ca_find_key(u32 key) { struct tcp_congestion_ops *e; list_for_each_entry_rcu(e, &tcp_cong_list, list) { if (e->key == key) return e; } return NULL; } |
317a76f9a [TCP]: Add plugga... |
60 |
/* |
d08df601a Various typo fixes. |
61 |
* Attach new congestion control algorithm to the list |
317a76f9a [TCP]: Add plugga... |
62 63 64 65 66 |
* of available options. */ int tcp_register_congestion_control(struct tcp_congestion_ops *ca) { int ret = 0; |
e97991832 tcp: make undo_cw... |
67 68 69 |
/* all algorithms must implement these */ if (!ca->ssthresh || !ca->undo_cwnd || !(ca->cong_avoid || ca->cong_control)) { |
afd465030 net: ipv4: Standa... |
70 71 |
pr_err("%s does not implement required ops ", ca->name); |
317a76f9a [TCP]: Add plugga... |
72 73 |
return -EINVAL; } |
c5c6a8ab4 net: tcp: add key... |
74 |
ca->key = jhash(ca->name, sizeof(ca->name), strlen(ca->name)); |
317a76f9a [TCP]: Add plugga... |
75 |
spin_lock(&tcp_cong_list_lock); |
c5c6a8ab4 net: tcp: add key... |
76 77 78 79 |
if (ca->key == TCP_CA_UNSPEC || tcp_ca_find_key(ca->key)) { pr_notice("%s already registered or non-unique key ", ca->name); |
317a76f9a [TCP]: Add plugga... |
80 81 |
ret = -EEXIST; } else { |
3d2573f7e [TCP]: default co... |
82 |
list_add_tail_rcu(&ca->list, &tcp_cong_list); |
db2855ae2 tcp: silence regi... |
83 84 |
pr_debug("%s registered ", ca->name); |
317a76f9a [TCP]: Add plugga... |
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
} spin_unlock(&tcp_cong_list_lock); return ret; } EXPORT_SYMBOL_GPL(tcp_register_congestion_control); /* * Remove congestion control algorithm, called from * the module's remove function. Module ref counts are used * to ensure that this can't be done till all sockets using * that method are closed. */ void tcp_unregister_congestion_control(struct tcp_congestion_ops *ca) { spin_lock(&tcp_cong_list_lock); list_del_rcu(&ca->list); spin_unlock(&tcp_cong_list_lock); |
c5c6a8ab4 net: tcp: add key... |
103 104 105 106 107 108 109 110 111 |
/* Wait for outstanding readers to complete before the * module gets removed entirely. * * A try_module_get() should fail by now as our module is * in "going" state since no refs are held anymore and * module_exit() handler being called. */ synchronize_rcu(); |
317a76f9a [TCP]: Add plugga... |
112 113 |
} EXPORT_SYMBOL_GPL(tcp_unregister_congestion_control); |
6670e1524 tcp: Namespace-if... |
114 |
u32 tcp_ca_get_key_by_name(struct net *net, const char *name, bool *ecn_ca) |
c5c6a8ab4 net: tcp: add key... |
115 116 |
{ const struct tcp_congestion_ops *ca; |
c3a8d9474 tcp: use dctcp if... |
117 |
u32 key = TCP_CA_UNSPEC; |
c5c6a8ab4 net: tcp: add key... |
118 119 120 121 |
might_sleep(); rcu_read_lock(); |
6670e1524 tcp: Namespace-if... |
122 |
ca = tcp_ca_find_autoload(net, name); |
c3a8d9474 tcp: use dctcp if... |
123 124 125 126 |
if (ca) { key = ca->key; *ecn_ca = ca->flags & TCP_CONG_NEEDS_ECN; } |
c5c6a8ab4 net: tcp: add key... |
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
rcu_read_unlock(); return key; } EXPORT_SYMBOL_GPL(tcp_ca_get_key_by_name); char *tcp_ca_get_name_by_key(u32 key, char *buffer) { const struct tcp_congestion_ops *ca; char *ret = NULL; rcu_read_lock(); ca = tcp_ca_find_key(key); if (ca) ret = strncpy(buffer, ca->name, TCP_CA_NAME_MAX); rcu_read_unlock(); return ret; } EXPORT_SYMBOL_GPL(tcp_ca_get_name_by_key); |
317a76f9a [TCP]: Add plugga... |
148 |
/* Assign choice of congestion control. */ |
55d8694fa net: tcp: assign ... |
149 |
void tcp_assign_congestion_control(struct sock *sk) |
317a76f9a [TCP]: Add plugga... |
150 |
{ |
6670e1524 tcp: Namespace-if... |
151 |
struct net *net = sock_net(sk); |
6687e988d [ICSK]: Move TCP ... |
152 |
struct inet_connection_sock *icsk = inet_csk(sk); |
6670e1524 tcp: Namespace-if... |
153 |
const struct tcp_congestion_ops *ca; |
317a76f9a [TCP]: Add plugga... |
154 |
|
55d8694fa net: tcp: assign ... |
155 |
rcu_read_lock(); |
6670e1524 tcp: Namespace-if... |
156 |
ca = rcu_dereference(net->ipv4.tcp_congestion_control); |
0baf26b0f bpf: tcp: Support... |
157 |
if (unlikely(!bpf_try_module_get(ca, ca->owner))) |
6670e1524 tcp: Namespace-if... |
158 159 |
ca = &tcp_reno; icsk->icsk_ca_ops = ca; |
55d8694fa net: tcp: assign ... |
160 |
rcu_read_unlock(); |
6670e1524 tcp: Namespace-if... |
161 |
memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv)); |
6ac705b18 tcp: remove tcp_e... |
162 163 164 165 |
if (ca->flags & TCP_CONG_NEEDS_ECN) INET_ECN_xmit(sk); else INET_ECN_dontxmit(sk); |
55d8694fa net: tcp: assign ... |
166 167 168 169 |
} void tcp_init_congestion_control(struct sock *sk) { |
8919a9b31 tcp: Only init co... |
170 |
struct inet_connection_sock *icsk = inet_csk(sk); |
317a76f9a [TCP]: Add plugga... |
171 |
|
44abafc4c tcp: disallow cwn... |
172 |
tcp_sk(sk)->prior_ssthresh = 0; |
6687e988d [ICSK]: Move TCP ... |
173 174 |
if (icsk->icsk_ca_ops->init) icsk->icsk_ca_ops->init(sk); |
6ac705b18 tcp: remove tcp_e... |
175 176 177 178 |
if (tcp_ca_needs_ecn(sk)) INET_ECN_xmit(sk); else INET_ECN_dontxmit(sk); |
8919a9b31 tcp: Only init co... |
179 |
icsk->icsk_ca_initialized = 1; |
317a76f9a [TCP]: Add plugga... |
180 |
} |
ebfa00c57 tcp: fix refcnt l... |
181 182 |
static void tcp_reinit_congestion_control(struct sock *sk, const struct tcp_congestion_ops *ca) |
29ba4fffd net: tcp: refacto... |
183 184 185 186 187 |
{ struct inet_connection_sock *icsk = inet_csk(sk); tcp_cleanup_congestion_control(sk); icsk->icsk_ca_ops = ca; |
9f950415e tcp: fix child so... |
188 |
icsk->icsk_ca_setsockopt = 1; |
c12014440 tcp: memset ca_pr... |
189 |
memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv)); |
29ba4fffd net: tcp: refacto... |
190 |
|
55472017a tcp: Set INET_ECN... |
191 192 193 194 |
if (ca->flags & TCP_CONG_NEEDS_ECN) INET_ECN_xmit(sk); else INET_ECN_dontxmit(sk); |
ce69e563b tcp: make sure li... |
195 |
if (!((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) |
6ac705b18 tcp: remove tcp_e... |
196 |
tcp_init_congestion_control(sk); |
29ba4fffd net: tcp: refacto... |
197 |
} |
317a76f9a [TCP]: Add plugga... |
198 |
/* Manage refcounts on socket close. */ |
6687e988d [ICSK]: Move TCP ... |
199 |
void tcp_cleanup_congestion_control(struct sock *sk) |
317a76f9a [TCP]: Add plugga... |
200 |
{ |
6687e988d [ICSK]: Move TCP ... |
201 202 203 204 |
struct inet_connection_sock *icsk = inet_csk(sk); if (icsk->icsk_ca_ops->release) icsk->icsk_ca_ops->release(sk); |
0baf26b0f bpf: tcp: Support... |
205 |
bpf_module_put(icsk->icsk_ca_ops, icsk->icsk_ca_ops->owner); |
317a76f9a [TCP]: Add plugga... |
206 207 208 |
} /* Used by sysctl to change default congestion control */ |
6670e1524 tcp: Namespace-if... |
209 |
int tcp_set_default_congestion_control(struct net *net, const char *name) |
317a76f9a [TCP]: Add plugga... |
210 211 |
{ struct tcp_congestion_ops *ca; |
6670e1524 tcp: Namespace-if... |
212 213 |
const struct tcp_congestion_ops *prev; int ret; |
317a76f9a [TCP]: Add plugga... |
214 |
|
6670e1524 tcp: Namespace-if... |
215 216 217 218 |
rcu_read_lock(); ca = tcp_ca_find_autoload(net, name); if (!ca) { ret = -ENOENT; |
0baf26b0f bpf: tcp: Support... |
219 |
} else if (!bpf_try_module_get(ca, ca->owner)) { |
6670e1524 tcp: Namespace-if... |
220 221 222 223 |
ret = -EBUSY; } else { prev = xchg(&net->ipv4.tcp_congestion_control, ca); if (prev) |
0baf26b0f bpf: tcp: Support... |
224 |
bpf_module_put(prev, prev->owner); |
317a76f9a [TCP]: Add plugga... |
225 |
|
6670e1524 tcp: Namespace-if... |
226 |
ca->flags |= TCP_CONG_NON_RESTRICTED; |
317a76f9a [TCP]: Add plugga... |
227 228 |
ret = 0; } |
6670e1524 tcp: Namespace-if... |
229 |
rcu_read_unlock(); |
317a76f9a [TCP]: Add plugga... |
230 231 232 |
return ret; } |
b1736a714 [TCP]: Set defaul... |
233 234 235 |
/* Set default value from kernel configuration at bootup */ static int __init tcp_congestion_default(void) { |
6670e1524 tcp: Namespace-if... |
236 237 |
return tcp_set_default_congestion_control(&init_net, CONFIG_DEFAULT_TCP_CONG); |
b1736a714 [TCP]: Set defaul... |
238 239 |
} late_initcall(tcp_congestion_default); |
3ff825b28 [TCP]: Add tcp_av... |
240 241 242 243 244 245 246 247 248 249 250 |
/* Build string with list of available congestion control values */ void tcp_get_available_congestion_control(char *buf, size_t maxlen) { struct tcp_congestion_ops *ca; size_t offs = 0; rcu_read_lock(); list_for_each_entry_rcu(ca, &tcp_cong_list, list) { offs += snprintf(buf + offs, maxlen - offs, "%s%s", offs == 0 ? "" : " ", ca->name); |
9bb59a21f tcp: warn if offs... |
251 252 253 |
if (WARN_ON_ONCE(offs >= maxlen)) break; |
3ff825b28 [TCP]: Add tcp_av... |
254 255 256 |
} rcu_read_unlock(); } |
317a76f9a [TCP]: Add plugga... |
257 |
/* Get current default congestion control */ |
6670e1524 tcp: Namespace-if... |
258 |
void tcp_get_default_congestion_control(struct net *net, char *name) |
317a76f9a [TCP]: Add plugga... |
259 |
{ |
6670e1524 tcp: Namespace-if... |
260 |
const struct tcp_congestion_ops *ca; |
317a76f9a [TCP]: Add plugga... |
261 262 |
rcu_read_lock(); |
6670e1524 tcp: Namespace-if... |
263 |
ca = rcu_dereference(net->ipv4.tcp_congestion_control); |
317a76f9a [TCP]: Add plugga... |
264 265 266 |
strncpy(name, ca->name, TCP_CA_NAME_MAX); rcu_read_unlock(); } |
ce7bc3bf1 [TCP]: Restrict c... |
267 268 269 270 271 272 273 274 275 |
/* Built list of non-restricted congestion control values */ void tcp_get_allowed_congestion_control(char *buf, size_t maxlen) { struct tcp_congestion_ops *ca; size_t offs = 0; *buf = '\0'; rcu_read_lock(); list_for_each_entry_rcu(ca, &tcp_cong_list, list) { |
164891aad [TCP]: Congestion... |
276 |
if (!(ca->flags & TCP_CONG_NON_RESTRICTED)) |
ce7bc3bf1 [TCP]: Restrict c... |
277 278 279 280 |
continue; offs += snprintf(buf + offs, maxlen - offs, "%s%s", offs == 0 ? "" : " ", ca->name); |
9bb59a21f tcp: warn if offs... |
281 282 283 |
if (WARN_ON_ONCE(offs >= maxlen)) break; |
ce7bc3bf1 [TCP]: Restrict c... |
284 285 286 287 288 289 290 291 |
} rcu_read_unlock(); } /* Change list of non-restricted congestion control */ int tcp_set_allowed_congestion_control(char *val) { struct tcp_congestion_ops *ca; |
c34186ed0 net/ipv4: Elimina... |
292 |
char *saved_clone, *clone, *name; |
ce7bc3bf1 [TCP]: Restrict c... |
293 |
int ret = 0; |
c34186ed0 net/ipv4: Elimina... |
294 |
saved_clone = clone = kstrdup(val, GFP_USER); |
ce7bc3bf1 [TCP]: Restrict c... |
295 296 297 298 299 300 301 302 303 304 305 306 |
if (!clone) return -ENOMEM; spin_lock(&tcp_cong_list_lock); /* pass 1 check for bad entries */ while ((name = strsep(&clone, " ")) && *name) { ca = tcp_ca_find(name); if (!ca) { ret = -ENOENT; goto out; } } |
164891aad [TCP]: Congestion... |
307 |
/* pass 2 clear old values */ |
ce7bc3bf1 [TCP]: Restrict c... |
308 |
list_for_each_entry_rcu(ca, &tcp_cong_list, list) |
164891aad [TCP]: Congestion... |
309 |
ca->flags &= ~TCP_CONG_NON_RESTRICTED; |
ce7bc3bf1 [TCP]: Restrict c... |
310 311 312 313 314 315 |
/* pass 3 mark as allowed */ while ((name = strsep(&val, " ")) && *name) { ca = tcp_ca_find(name); WARN_ON(!ca); if (ca) |
164891aad [TCP]: Congestion... |
316 |
ca->flags |= TCP_CONG_NON_RESTRICTED; |
ce7bc3bf1 [TCP]: Restrict c... |
317 318 319 |
} out: spin_unlock(&tcp_cong_list_lock); |
c34186ed0 net/ipv4: Elimina... |
320 |
kfree(saved_clone); |
ce7bc3bf1 [TCP]: Restrict c... |
321 322 323 |
return ret; } |
91b5b21c7 bpf: Add support ... |
324 325 326 327 328 |
/* Change congestion control for socket. If load is false, then it is the * responsibility of the caller to call tcp_init_congestion_control or * tcp_reinit_congestion_control (if the current congestion control was * already initialized. */ |
8d650cded tcp: fix tcp_set_... |
329 |
int tcp_set_congestion_control(struct sock *sk, const char *name, bool load, |
29a949325 tcp: simplify tcp... |
330 |
bool cap_net_admin) |
5f8ef48d2 [TCP]: Allow choo... |
331 |
{ |
6687e988d [ICSK]: Move TCP ... |
332 |
struct inet_connection_sock *icsk = inet_csk(sk); |
c5c6a8ab4 net: tcp: add key... |
333 |
const struct tcp_congestion_ops *ca; |
5f8ef48d2 [TCP]: Allow choo... |
334 |
int err = 0; |
c5c6a8ab4 net: tcp: add key... |
335 336 |
if (icsk->icsk_ca_dst_locked) return -EPERM; |
4d4d3d1e8 [TCP]: Congestion... |
337 |
|
c5c6a8ab4 net: tcp: add key... |
338 |
rcu_read_lock(); |
91b5b21c7 bpf: Add support ... |
339 340 341 |
if (!load) ca = tcp_ca_find(name); else |
6670e1524 tcp: Namespace-if... |
342 |
ca = tcp_ca_find_autoload(sock_net(sk), name); |
c5c6a8ab4 net: tcp: add key... |
343 |
/* No change asking for existing value */ |
9f950415e tcp: fix child so... |
344 345 |
if (ca == icsk->icsk_ca_ops) { icsk->icsk_ca_setsockopt = 1; |
5f8ef48d2 [TCP]: Allow choo... |
346 |
goto out; |
9f950415e tcp: fix child so... |
347 |
} |
6670e1524 tcp: Namespace-if... |
348 |
|
5050bef87 tcp: Simplify tcp... |
349 |
if (!ca) |
5f8ef48d2 [TCP]: Allow choo... |
350 |
err = -ENOENT; |
5050bef87 tcp: Simplify tcp... |
351 |
else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || cap_net_admin)) |
ce7bc3bf1 [TCP]: Restrict c... |
352 |
err = -EPERM; |
5050bef87 tcp: Simplify tcp... |
353 |
else if (!bpf_try_module_get(ca, ca->owner)) |
5f8ef48d2 [TCP]: Allow choo... |
354 |
err = -EBUSY; |
5050bef87 tcp: Simplify tcp... |
355 |
else |
29ba4fffd net: tcp: refacto... |
356 |
tcp_reinit_congestion_control(sk, ca); |
5f8ef48d2 [TCP]: Allow choo... |
357 358 359 360 |
out: rcu_read_unlock(); return err; } |
9f9843a75 tcp: properly han... |
361 362 363 364 365 366 367 368 |
/* Slow start is used when congestion window is no greater than the slow start * threshold. We base on RFC2581 and also handle stretch ACKs properly. * We do not implement RFC3465 Appropriate Byte Counting (ABC) per se but * something better;) a packet is only considered (s)acked in its entirety to * defend the ACK attacks described in the RFC. Slow start processes a stretch * ACK of degree N as if N acks of degree 1 are received back to back except * ABC caps N to 2. Slow start exits when cwnd grows over ssthresh and * returns the leftover acks to adjust cwnd in congestion avoidance mode. |
40efc6fa1 [TCP]: less inline's |
369 |
*/ |
e73ebb088 tcp: stretch ACK ... |
370 |
u32 tcp_slow_start(struct tcp_sock *tp, u32 acked) |
40efc6fa1 [TCP]: less inline's |
371 |
{ |
76174004a tcp: do not slow ... |
372 |
u32 cwnd = min(tp->snd_cwnd + acked, tp->snd_ssthresh); |
a02ba0416 [TCP] slow start:... |
373 |
|
e73ebb088 tcp: stretch ACK ... |
374 |
acked -= cwnd - tp->snd_cwnd; |
9f9843a75 tcp: properly han... |
375 |
tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp); |
e73ebb088 tcp: stretch ACK ... |
376 377 |
return acked; |
40efc6fa1 [TCP]: less inline's |
378 379 |
} EXPORT_SYMBOL_GPL(tcp_slow_start); |
814d488c6 tcp: fix the timi... |
380 381 382 |
/* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd (or alternative w), * for every packet that was ACKed. */ |
e73ebb088 tcp: stretch ACK ... |
383 |
void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w, u32 acked) |
758ce5c8d tcp: add helper f... |
384 |
{ |
9949afa42 tcp: fix tcp_cong... |
385 386 387 388 389 |
/* If credits accumulated at a higher w, apply them gently now. */ if (tp->snd_cwnd_cnt >= w) { tp->snd_cwnd_cnt = 0; tp->snd_cwnd++; } |
814d488c6 tcp: fix the timi... |
390 |
tp->snd_cwnd_cnt += acked; |
758ce5c8d tcp: add helper f... |
391 |
if (tp->snd_cwnd_cnt >= w) { |
814d488c6 tcp: fix the timi... |
392 393 394 395 |
u32 delta = tp->snd_cwnd_cnt / w; tp->snd_cwnd_cnt -= delta * w; tp->snd_cwnd += delta; |
758ce5c8d tcp: add helper f... |
396 |
} |
814d488c6 tcp: fix the timi... |
397 |
tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_cwnd_clamp); |
758ce5c8d tcp: add helper f... |
398 399 |
} EXPORT_SYMBOL_GPL(tcp_cong_avoid_ai); |
317a76f9a [TCP]: Add plugga... |
400 401 402 403 404 405 406 |
/* * TCP Reno congestion control * This is special case used for fallback as well. */ /* This is Jacobson's slow start and congestion avoidance. * SIGCOMM '88, p. 328. */ |
249015515 tcp: remove in_fl... |
407 |
void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 acked) |
317a76f9a [TCP]: Add plugga... |
408 |
{ |
6687e988d [ICSK]: Move TCP ... |
409 |
struct tcp_sock *tp = tcp_sk(sk); |
249015515 tcp: remove in_fl... |
410 |
if (!tcp_is_cwnd_limited(sk)) |
317a76f9a [TCP]: Add plugga... |
411 |
return; |
7faffa1c7 [TCP]: add tcp_sl... |
412 |
/* In "safe" area, increase. */ |
071d5080e tcp: add tcp_in_s... |
413 |
if (tcp_in_slow_start(tp)) { |
c22bdca94 tcp: fix stretch ... |
414 415 416 417 |
acked = tcp_slow_start(tp, acked); if (!acked) return; } |
e905a9eda [NET] IPV4: Fix w... |
418 |
/* In dangerous area, increase slowly. */ |
c22bdca94 tcp: fix stretch ... |
419 |
tcp_cong_avoid_ai(tp, tp->snd_cwnd, acked); |
317a76f9a [TCP]: Add plugga... |
420 421 422 423 |
} EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid); /* Slow start threshold is half the congestion window (min 2) */ |
6687e988d [ICSK]: Move TCP ... |
424 |
u32 tcp_reno_ssthresh(struct sock *sk) |
317a76f9a [TCP]: Add plugga... |
425 |
{ |
6687e988d [ICSK]: Move TCP ... |
426 |
const struct tcp_sock *tp = tcp_sk(sk); |
688d1945b tcp: whitespace f... |
427 |
|
317a76f9a [TCP]: Add plugga... |
428 429 430 |
return max(tp->snd_cwnd >> 1U, 2U); } EXPORT_SYMBOL_GPL(tcp_reno_ssthresh); |
e97991832 tcp: make undo_cw... |
431 432 433 |
u32 tcp_reno_undo_cwnd(struct sock *sk) { const struct tcp_sock *tp = tcp_sk(sk); |
4faf78399 tcp: fix cwnd und... |
434 |
return max(tp->snd_cwnd, tp->prior_cwnd); |
e97991832 tcp: make undo_cw... |
435 436 |
} EXPORT_SYMBOL_GPL(tcp_reno_undo_cwnd); |
317a76f9a [TCP]: Add plugga... |
437 |
struct tcp_congestion_ops tcp_reno = { |
164891aad [TCP]: Congestion... |
438 |
.flags = TCP_CONG_NON_RESTRICTED, |
317a76f9a [TCP]: Add plugga... |
439 440 441 442 |
.name = "reno", .owner = THIS_MODULE, .ssthresh = tcp_reno_ssthresh, .cong_avoid = tcp_reno_cong_avoid, |
e97991832 tcp: make undo_cw... |
443 |
.undo_cwnd = tcp_reno_undo_cwnd, |
317a76f9a [TCP]: Add plugga... |
444 |
}; |