|
@@ -189,8 +189,8 @@ void tcp_init_congestion_control(struct sock *sk)
|
|
|
INET_ECN_dontxmit(sk);
|
|
|
}
|
|
|
|
|
|
-static void tcp_reinit_congestion_control(struct sock *sk,
|
|
|
- const struct tcp_congestion_ops *ca)
|
|
|
+void tcp_reinit_congestion_control(struct sock *sk,
|
|
|
+ const struct tcp_congestion_ops *ca)
|
|
|
{
|
|
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
|
|
|
|
@@ -333,8 +333,12 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/* Change congestion control for socket */
|
|
|
-int tcp_set_congestion_control(struct sock *sk, const char *name)
|
|
|
+/* 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.
|
|
|
+ */
|
|
|
+int tcp_set_congestion_control(struct sock *sk, const char *name, bool load)
|
|
|
{
|
|
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
|
|
const struct tcp_congestion_ops *ca;
|
|
@@ -344,21 +348,29 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
|
|
|
return -EPERM;
|
|
|
|
|
|
rcu_read_lock();
|
|
|
- ca = __tcp_ca_find_autoload(name);
|
|
|
+ if (!load)
|
|
|
+ ca = tcp_ca_find(name);
|
|
|
+ else
|
|
|
+ ca = __tcp_ca_find_autoload(name);
|
|
|
/* No change asking for existing value */
|
|
|
if (ca == icsk->icsk_ca_ops) {
|
|
|
icsk->icsk_ca_setsockopt = 1;
|
|
|
goto out;
|
|
|
}
|
|
|
- if (!ca)
|
|
|
+ if (!ca) {
|
|
|
err = -ENOENT;
|
|
|
- else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) ||
|
|
|
- ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)))
|
|
|
+ } else if (!load) {
|
|
|
+ icsk->icsk_ca_ops = ca;
|
|
|
+ if (!try_module_get(ca->owner))
|
|
|
+ err = -EBUSY;
|
|
|
+ } else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) ||
|
|
|
+ ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))) {
|
|
|
err = -EPERM;
|
|
|
- else if (!try_module_get(ca->owner))
|
|
|
+ } else if (!try_module_get(ca->owner)) {
|
|
|
err = -EBUSY;
|
|
|
- else
|
|
|
+ } else {
|
|
|
tcp_reinit_congestion_control(sk, ca);
|
|
|
+ }
|
|
|
out:
|
|
|
rcu_read_unlock();
|
|
|
return err;
|