aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_cong.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_cong.c')
-rw-r--r--net/ipv4/tcp_cong.c55
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)
74EXPORT_SYMBOL_GPL(tcp_unregister_congestion_control); 74EXPORT_SYMBOL_GPL(tcp_unregister_congestion_control);
75 75
76/* Assign choice of congestion control. */ 76/* Assign choice of congestion control. */
77void tcp_init_congestion_control(struct sock *sk) 77void 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 }
92out:
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
102void 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}
143late_initcall(tcp_congestion_default); 153late_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 */
147void tcp_get_available_congestion_control(char *buf, size_t maxlen) 156void 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 */
235int tcp_set_congestion_control(struct sock *sk, const char *name) 241int 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 */
288int tcp_slow_start(struct tcp_sock *tp, u32 acked) 294void 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}
298EXPORT_SYMBOL_GPL(tcp_slow_start); 302EXPORT_SYMBOL_GPL(tcp_slow_start);
299 303
@@ -337,6 +341,7 @@ EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid);
337u32 tcp_reno_ssthresh(struct sock *sk) 341u32 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}
342EXPORT_SYMBOL_GPL(tcp_reno_ssthresh); 347EXPORT_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 */
356struct 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};
362EXPORT_SYMBOL_GPL(tcp_init_congestion_ops);