diff options
Diffstat (limited to 'net/ipv4/tcp_cong.c')
-rw-r--r-- | net/ipv4/tcp_cong.c | 55 |
1 files changed, 24 insertions, 31 deletions
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 7b09d8b49fa5..b1c5970d47a1 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
@@ -74,24 +74,34 @@ void tcp_unregister_congestion_control(struct tcp_congestion_ops *ca) | |||
74 | EXPORT_SYMBOL_GPL(tcp_unregister_congestion_control); | 74 | EXPORT_SYMBOL_GPL(tcp_unregister_congestion_control); |
75 | 75 | ||
76 | /* Assign choice of congestion control. */ | 76 | /* Assign choice of congestion control. */ |
77 | void tcp_init_congestion_control(struct sock *sk) | 77 | void tcp_assign_congestion_control(struct sock *sk) |
78 | { | 78 | { |
79 | struct inet_connection_sock *icsk = inet_csk(sk); | 79 | struct inet_connection_sock *icsk = inet_csk(sk); |
80 | struct tcp_congestion_ops *ca; | 80 | struct tcp_congestion_ops *ca; |
81 | 81 | ||
82 | /* if no choice made yet assign the current value set as default */ | 82 | rcu_read_lock(); |
83 | if (icsk->icsk_ca_ops == &tcp_init_congestion_ops) { | 83 | list_for_each_entry_rcu(ca, &tcp_cong_list, list) { |
84 | rcu_read_lock(); | 84 | if (likely(try_module_get(ca->owner))) { |
85 | list_for_each_entry_rcu(ca, &tcp_cong_list, list) { | 85 | icsk->icsk_ca_ops = ca; |
86 | if (try_module_get(ca->owner)) { | 86 | goto out; |
87 | icsk->icsk_ca_ops = ca; | ||
88 | break; | ||
89 | } | ||
90 | |||
91 | /* fallback to next available */ | ||
92 | } | 87 | } |
93 | rcu_read_unlock(); | 88 | /* Fallback to next available. The last really |
89 | * guaranteed fallback is Reno from this list. | ||
90 | */ | ||
94 | } | 91 | } |
92 | out: | ||
93 | rcu_read_unlock(); | ||
94 | |||
95 | /* Clear out private data before diag gets it and | ||
96 | * the ca has not been initialized. | ||
97 | */ | ||
98 | if (ca->get_info) | ||
99 | memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv)); | ||
100 | } | ||
101 | |||
102 | void tcp_init_congestion_control(struct sock *sk) | ||
103 | { | ||
104 | const struct inet_connection_sock *icsk = inet_csk(sk); | ||
95 | 105 | ||
96 | if (icsk->icsk_ca_ops->init) | 106 | if (icsk->icsk_ca_ops->init) |
97 | icsk->icsk_ca_ops->init(sk); | 107 | icsk->icsk_ca_ops->init(sk); |
@@ -142,7 +152,6 @@ static int __init tcp_congestion_default(void) | |||
142 | } | 152 | } |
143 | late_initcall(tcp_congestion_default); | 153 | late_initcall(tcp_congestion_default); |
144 | 154 | ||
145 | |||
146 | /* Build string with list of available congestion control values */ | 155 | /* Build string with list of available congestion control values */ |
147 | void tcp_get_available_congestion_control(char *buf, size_t maxlen) | 156 | void tcp_get_available_congestion_control(char *buf, size_t maxlen) |
148 | { | 157 | { |
@@ -154,7 +163,6 @@ void tcp_get_available_congestion_control(char *buf, size_t maxlen) | |||
154 | offs += snprintf(buf + offs, maxlen - offs, | 163 | offs += snprintf(buf + offs, maxlen - offs, |
155 | "%s%s", | 164 | "%s%s", |
156 | offs == 0 ? "" : " ", ca->name); | 165 | offs == 0 ? "" : " ", ca->name); |
157 | |||
158 | } | 166 | } |
159 | rcu_read_unlock(); | 167 | rcu_read_unlock(); |
160 | } | 168 | } |
@@ -186,7 +194,6 @@ void tcp_get_allowed_congestion_control(char *buf, size_t maxlen) | |||
186 | offs += snprintf(buf + offs, maxlen - offs, | 194 | offs += snprintf(buf + offs, maxlen - offs, |
187 | "%s%s", | 195 | "%s%s", |
188 | offs == 0 ? "" : " ", ca->name); | 196 | offs == 0 ? "" : " ", ca->name); |
189 | |||
190 | } | 197 | } |
191 | rcu_read_unlock(); | 198 | rcu_read_unlock(); |
192 | } | 199 | } |
@@ -230,7 +237,6 @@ out: | |||
230 | return ret; | 237 | return ret; |
231 | } | 238 | } |
232 | 239 | ||
233 | |||
234 | /* Change congestion control for socket */ | 240 | /* Change congestion control for socket */ |
235 | int tcp_set_congestion_control(struct sock *sk, const char *name) | 241 | int tcp_set_congestion_control(struct sock *sk, const char *name) |
236 | { | 242 | { |
@@ -285,15 +291,13 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) | |||
285 | * ABC caps N to 2. Slow start exits when cwnd grows over ssthresh and | 291 | * ABC caps N to 2. Slow start exits when cwnd grows over ssthresh and |
286 | * returns the leftover acks to adjust cwnd in congestion avoidance mode. | 292 | * returns the leftover acks to adjust cwnd in congestion avoidance mode. |
287 | */ | 293 | */ |
288 | int tcp_slow_start(struct tcp_sock *tp, u32 acked) | 294 | void tcp_slow_start(struct tcp_sock *tp, u32 acked) |
289 | { | 295 | { |
290 | u32 cwnd = tp->snd_cwnd + acked; | 296 | u32 cwnd = tp->snd_cwnd + acked; |
291 | 297 | ||
292 | if (cwnd > tp->snd_ssthresh) | 298 | if (cwnd > tp->snd_ssthresh) |
293 | cwnd = tp->snd_ssthresh + 1; | 299 | cwnd = tp->snd_ssthresh + 1; |
294 | acked -= cwnd - tp->snd_cwnd; | ||
295 | tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp); | 300 | tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp); |
296 | return acked; | ||
297 | } | 301 | } |
298 | EXPORT_SYMBOL_GPL(tcp_slow_start); | 302 | EXPORT_SYMBOL_GPL(tcp_slow_start); |
299 | 303 | ||
@@ -337,6 +341,7 @@ EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid); | |||
337 | u32 tcp_reno_ssthresh(struct sock *sk) | 341 | u32 tcp_reno_ssthresh(struct sock *sk) |
338 | { | 342 | { |
339 | const struct tcp_sock *tp = tcp_sk(sk); | 343 | const struct tcp_sock *tp = tcp_sk(sk); |
344 | |||
340 | return max(tp->snd_cwnd >> 1U, 2U); | 345 | return max(tp->snd_cwnd >> 1U, 2U); |
341 | } | 346 | } |
342 | EXPORT_SYMBOL_GPL(tcp_reno_ssthresh); | 347 | EXPORT_SYMBOL_GPL(tcp_reno_ssthresh); |
@@ -348,15 +353,3 @@ struct tcp_congestion_ops tcp_reno = { | |||
348 | .ssthresh = tcp_reno_ssthresh, | 353 | .ssthresh = tcp_reno_ssthresh, |
349 | .cong_avoid = tcp_reno_cong_avoid, | 354 | .cong_avoid = tcp_reno_cong_avoid, |
350 | }; | 355 | }; |
351 | |||
352 | /* Initial congestion control used (until SYN) | ||
353 | * really reno under another name so we can tell difference | ||
354 | * during tcp_set_default_congestion_control | ||
355 | */ | ||
356 | struct tcp_congestion_ops tcp_init_congestion_ops = { | ||
357 | .name = "", | ||
358 | .owner = THIS_MODULE, | ||
359 | .ssthresh = tcp_reno_ssthresh, | ||
360 | .cong_avoid = tcp_reno_cong_avoid, | ||
361 | }; | ||
362 | EXPORT_SYMBOL_GPL(tcp_init_congestion_ops); | ||