bpf: Add support for changing congestion control
Added support for changing congestion control for SOCK_OPS bpf programs through the setsockopt bpf helper function. It also adds a new SOCK_OPS op, BPF_SOCK_OPS_NEEDS_ECN, that is needed for congestion controls, like dctcp, that need to enable ECN in the SYN packets. Signed-off-by: Lawrence Brakmo <brakmo@fb.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
d9925368a6
commit
91b5b21c7c
@@ -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;
|
||||
|
Reference in New Issue
Block a user