aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_cong.c
diff options
context:
space:
mode:
authorStephen Hemminger <stephen@networkplumber.org>2017-11-14 11:25:49 -0500
committerDavid S. Miller <davem@davemloft.net>2017-11-15 00:09:52 -0500
commit6670e152447732ba90626f36dfc015a13fbf150e (patch)
tree0848d15b1d27139ee651c8ecae0136bb679f205a /net/ipv4/tcp_cong.c
parent11bf284f81b46f59d5f4a4522c13aa7852cfd560 (diff)
tcp: Namespace-ify sysctl_tcp_default_congestion_control
Make default TCP default congestion control to a per namespace value. This changes default congestion control to a pointer to congestion ops (rather than implicit as first element of available lsit). The congestion control setting of new namespaces is inherited from the current setting of the root namespace. Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_cong.c')
-rw-r--r--net/ipv4/tcp_cong.c76
1 files changed, 36 insertions, 40 deletions
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 2f26124fd160..bc6c02f16243 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -33,9 +33,11 @@ static struct tcp_congestion_ops *tcp_ca_find(const char *name)
33} 33}
34 34
35/* Must be called with rcu lock held */ 35/* Must be called with rcu lock held */
36static const struct tcp_congestion_ops *__tcp_ca_find_autoload(const char *name) 36static struct tcp_congestion_ops *tcp_ca_find_autoload(struct net *net,
37 const char *name)
37{ 38{
38 const struct tcp_congestion_ops *ca = tcp_ca_find(name); 39 struct tcp_congestion_ops *ca = tcp_ca_find(name);
40
39#ifdef CONFIG_MODULES 41#ifdef CONFIG_MODULES
40 if (!ca && capable(CAP_NET_ADMIN)) { 42 if (!ca && capable(CAP_NET_ADMIN)) {
41 rcu_read_unlock(); 43 rcu_read_unlock();
@@ -115,7 +117,7 @@ void tcp_unregister_congestion_control(struct tcp_congestion_ops *ca)
115} 117}
116EXPORT_SYMBOL_GPL(tcp_unregister_congestion_control); 118EXPORT_SYMBOL_GPL(tcp_unregister_congestion_control);
117 119
118u32 tcp_ca_get_key_by_name(const char *name, bool *ecn_ca) 120u32 tcp_ca_get_key_by_name(struct net *net, const char *name, bool *ecn_ca)
119{ 121{
120 const struct tcp_congestion_ops *ca; 122 const struct tcp_congestion_ops *ca;
121 u32 key = TCP_CA_UNSPEC; 123 u32 key = TCP_CA_UNSPEC;
@@ -123,7 +125,7 @@ u32 tcp_ca_get_key_by_name(const char *name, bool *ecn_ca)
123 might_sleep(); 125 might_sleep();
124 126
125 rcu_read_lock(); 127 rcu_read_lock();
126 ca = __tcp_ca_find_autoload(name); 128 ca = tcp_ca_find_autoload(net, name);
127 if (ca) { 129 if (ca) {
128 key = ca->key; 130 key = ca->key;
129 *ecn_ca = ca->flags & TCP_CONG_NEEDS_ECN; 131 *ecn_ca = ca->flags & TCP_CONG_NEEDS_ECN;
@@ -153,23 +155,18 @@ EXPORT_SYMBOL_GPL(tcp_ca_get_name_by_key);
153/* Assign choice of congestion control. */ 155/* Assign choice of congestion control. */
154void tcp_assign_congestion_control(struct sock *sk) 156void tcp_assign_congestion_control(struct sock *sk)
155{ 157{
158 struct net *net = sock_net(sk);
156 struct inet_connection_sock *icsk = inet_csk(sk); 159 struct inet_connection_sock *icsk = inet_csk(sk);
157 struct tcp_congestion_ops *ca; 160 const struct tcp_congestion_ops *ca;
158 161
159 rcu_read_lock(); 162 rcu_read_lock();
160 list_for_each_entry_rcu(ca, &tcp_cong_list, list) { 163 ca = rcu_dereference(net->ipv4.tcp_congestion_control);
161 if (likely(try_module_get(ca->owner))) { 164 if (unlikely(!try_module_get(ca->owner)))
162 icsk->icsk_ca_ops = ca; 165 ca = &tcp_reno;
163 goto out; 166 icsk->icsk_ca_ops = ca;
164 }
165 /* Fallback to next available. The last really
166 * guaranteed fallback is Reno from this list.
167 */
168 }
169out:
170 rcu_read_unlock(); 167 rcu_read_unlock();
171 memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
172 168
169 memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
173 if (ca->flags & TCP_CONG_NEEDS_ECN) 170 if (ca->flags & TCP_CONG_NEEDS_ECN)
174 INET_ECN_xmit(sk); 171 INET_ECN_xmit(sk);
175 else 172 else
@@ -214,29 +211,27 @@ void tcp_cleanup_congestion_control(struct sock *sk)
214} 211}
215 212
216/* Used by sysctl to change default congestion control */ 213/* Used by sysctl to change default congestion control */
217int tcp_set_default_congestion_control(const char *name) 214int tcp_set_default_congestion_control(struct net *net, const char *name)
218{ 215{
219 struct tcp_congestion_ops *ca; 216 struct tcp_congestion_ops *ca;
220 int ret = -ENOENT; 217 const struct tcp_congestion_ops *prev;
221 218 int ret;
222 spin_lock(&tcp_cong_list_lock);
223 ca = tcp_ca_find(name);
224#ifdef CONFIG_MODULES
225 if (!ca && capable(CAP_NET_ADMIN)) {
226 spin_unlock(&tcp_cong_list_lock);
227 219
228 request_module("tcp_%s", name); 220 rcu_read_lock();
229 spin_lock(&tcp_cong_list_lock); 221 ca = tcp_ca_find_autoload(net, name);
230 ca = tcp_ca_find(name); 222 if (!ca) {
231 } 223 ret = -ENOENT;
232#endif 224 } else if (!try_module_get(ca->owner)) {
225 ret = -EBUSY;
226 } else {
227 prev = xchg(&net->ipv4.tcp_congestion_control, ca);
228 if (prev)
229 module_put(prev->owner);
233 230
234 if (ca) { 231 ca->flags |= TCP_CONG_NON_RESTRICTED;
235 ca->flags |= TCP_CONG_NON_RESTRICTED; /* default is always allowed */
236 list_move(&ca->list, &tcp_cong_list);
237 ret = 0; 232 ret = 0;
238 } 233 }
239 spin_unlock(&tcp_cong_list_lock); 234 rcu_read_unlock();
240 235
241 return ret; 236 return ret;
242} 237}
@@ -244,7 +239,8 @@ int tcp_set_default_congestion_control(const char *name)
244/* Set default value from kernel configuration at bootup */ 239/* Set default value from kernel configuration at bootup */
245static int __init tcp_congestion_default(void) 240static int __init tcp_congestion_default(void)
246{ 241{
247 return tcp_set_default_congestion_control(CONFIG_DEFAULT_TCP_CONG); 242 return tcp_set_default_congestion_control(&init_net,
243 CONFIG_DEFAULT_TCP_CONG);
248} 244}
249late_initcall(tcp_congestion_default); 245late_initcall(tcp_congestion_default);
250 246
@@ -264,14 +260,12 @@ void tcp_get_available_congestion_control(char *buf, size_t maxlen)
264} 260}
265 261
266/* Get current default congestion control */ 262/* Get current default congestion control */
267void tcp_get_default_congestion_control(char *name) 263void tcp_get_default_congestion_control(struct net *net, char *name)
268{ 264{
269 struct tcp_congestion_ops *ca; 265 const struct tcp_congestion_ops *ca;
270 /* We will always have reno... */
271 BUG_ON(list_empty(&tcp_cong_list));
272 266
273 rcu_read_lock(); 267 rcu_read_lock();
274 ca = list_entry(tcp_cong_list.next, struct tcp_congestion_ops, list); 268 ca = rcu_dereference(net->ipv4.tcp_congestion_control);
275 strncpy(name, ca->name, TCP_CA_NAME_MAX); 269 strncpy(name, ca->name, TCP_CA_NAME_MAX);
276 rcu_read_unlock(); 270 rcu_read_unlock();
277} 271}
@@ -351,12 +345,14 @@ int tcp_set_congestion_control(struct sock *sk, const char *name, bool load, boo
351 if (!load) 345 if (!load)
352 ca = tcp_ca_find(name); 346 ca = tcp_ca_find(name);
353 else 347 else
354 ca = __tcp_ca_find_autoload(name); 348 ca = tcp_ca_find_autoload(sock_net(sk), name);
349
355 /* No change asking for existing value */ 350 /* No change asking for existing value */
356 if (ca == icsk->icsk_ca_ops) { 351 if (ca == icsk->icsk_ca_ops) {
357 icsk->icsk_ca_setsockopt = 1; 352 icsk->icsk_ca_setsockopt = 1;
358 goto out; 353 goto out;
359 } 354 }
355
360 if (!ca) { 356 if (!ca) {
361 err = -ENOENT; 357 err = -ENOENT;
362 } else if (!load) { 358 } else if (!load) {