Commit 1243a51f authored by Daniel Borkmann's avatar Daniel Borkmann Committed by Alexei Starovoitov

tcp, ulp: remove ulp bits from sockmap

In order to prepare sockmap logic to be used in combination with kTLS
we need to detangle it from ULP, and further split it in later commits
into a generic API.

Joint work with John.
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Signed-off-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 8b9088f8
...@@ -2057,7 +2057,6 @@ struct tcp_ulp_ops { ...@@ -2057,7 +2057,6 @@ struct tcp_ulp_ops {
int tcp_register_ulp(struct tcp_ulp_ops *type); int tcp_register_ulp(struct tcp_ulp_ops *type);
void tcp_unregister_ulp(struct tcp_ulp_ops *type); void tcp_unregister_ulp(struct tcp_ulp_ops *type);
int tcp_set_ulp(struct sock *sk, const char *name); int tcp_set_ulp(struct sock *sk, const char *name);
int tcp_set_ulp_id(struct sock *sk, const int ulp);
void tcp_get_available_ulp(char *buf, size_t len); void tcp_get_available_ulp(char *buf, size_t len);
void tcp_cleanup_ulp(struct sock *sk); void tcp_cleanup_ulp(struct sock *sk);
......
...@@ -182,6 +182,7 @@ enum { ...@@ -182,6 +182,7 @@ enum {
static struct proto *saved_tcpv6_prot __read_mostly; static struct proto *saved_tcpv6_prot __read_mostly;
static DEFINE_SPINLOCK(tcpv6_prot_lock); static DEFINE_SPINLOCK(tcpv6_prot_lock);
static struct proto bpf_tcp_prots[SOCKMAP_NUM_PROTS][SOCKMAP_NUM_CONFIGS]; static struct proto bpf_tcp_prots[SOCKMAP_NUM_PROTS][SOCKMAP_NUM_CONFIGS];
static void build_protos(struct proto prot[SOCKMAP_NUM_CONFIGS], static void build_protos(struct proto prot[SOCKMAP_NUM_CONFIGS],
struct proto *base) struct proto *base)
{ {
...@@ -239,6 +240,13 @@ static int bpf_tcp_init(struct sock *sk) ...@@ -239,6 +240,13 @@ static int bpf_tcp_init(struct sock *sk)
return 0; return 0;
} }
static int __init bpf_sock_init(void)
{
build_protos(bpf_tcp_prots[SOCKMAP_IPV4], &tcp_prot);
return 0;
}
core_initcall(bpf_sock_init);
static void smap_release_sock(struct smap_psock *psock, struct sock *sock); static void smap_release_sock(struct smap_psock *psock, struct sock *sock);
static int free_start_sg(struct sock *sk, struct sk_msg_buff *md, bool charge); static int free_start_sg(struct sock *sk, struct sk_msg_buff *md, bool charge);
...@@ -413,15 +421,6 @@ enum __sk_action { ...@@ -413,15 +421,6 @@ enum __sk_action {
__SK_NONE, __SK_NONE,
}; };
static struct tcp_ulp_ops bpf_tcp_ulp_ops __read_mostly = {
.name = "bpf_tcp",
.uid = TCP_ULP_BPF,
.user_visible = false,
.owner = NULL,
.init = bpf_tcp_init,
.release = bpf_tcp_release,
};
static int memcopy_from_iter(struct sock *sk, static int memcopy_from_iter(struct sock *sk,
struct sk_msg_buff *md, struct sk_msg_buff *md,
struct iov_iter *from, int bytes) struct iov_iter *from, int bytes)
...@@ -1236,16 +1235,6 @@ static void bpf_tcp_msg_add(struct smap_psock *psock, ...@@ -1236,16 +1235,6 @@ static void bpf_tcp_msg_add(struct smap_psock *psock,
bpf_prog_put(orig_tx_msg); bpf_prog_put(orig_tx_msg);
} }
static int bpf_tcp_ulp_register(void)
{
build_protos(bpf_tcp_prots[SOCKMAP_IPV4], &tcp_prot);
/* Once BPF TX ULP is registered it is never unregistered. It
* will be in the ULP list for the lifetime of the system. Doing
* duplicate registers is not a problem.
*/
return tcp_register_ulp(&bpf_tcp_ulp_ops);
}
static int smap_verdict_func(struct smap_psock *psock, struct sk_buff *skb) static int smap_verdict_func(struct smap_psock *psock, struct sk_buff *skb)
{ {
struct bpf_prog *prog = READ_ONCE(psock->bpf_verdict); struct bpf_prog *prog = READ_ONCE(psock->bpf_verdict);
...@@ -1491,7 +1480,7 @@ static void smap_release_sock(struct smap_psock *psock, struct sock *sock) ...@@ -1491,7 +1480,7 @@ static void smap_release_sock(struct smap_psock *psock, struct sock *sock)
{ {
if (refcount_dec_and_test(&psock->refcnt)) { if (refcount_dec_and_test(&psock->refcnt)) {
if (psock_is_smap_sk(sock)) if (psock_is_smap_sk(sock))
tcp_cleanup_ulp(sock); bpf_tcp_release(sock);
write_lock_bh(&sock->sk_callback_lock); write_lock_bh(&sock->sk_callback_lock);
smap_stop_sock(psock, sock); smap_stop_sock(psock, sock);
write_unlock_bh(&sock->sk_callback_lock); write_unlock_bh(&sock->sk_callback_lock);
...@@ -1666,10 +1655,6 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr) ...@@ -1666,10 +1655,6 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr)
attr->value_size != 4 || attr->map_flags & ~SOCK_CREATE_FLAG_MASK) attr->value_size != 4 || attr->map_flags & ~SOCK_CREATE_FLAG_MASK)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
err = bpf_tcp_ulp_register();
if (err && err != -EEXIST)
return ERR_PTR(err);
stab = kzalloc(sizeof(*stab), GFP_USER); stab = kzalloc(sizeof(*stab), GFP_USER);
if (!stab) if (!stab)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -1951,7 +1936,7 @@ static int __sock_map_ctx_update_elem(struct bpf_map *map, ...@@ -1951,7 +1936,7 @@ static int __sock_map_ctx_update_elem(struct bpf_map *map,
if (tx_msg) if (tx_msg)
bpf_tcp_msg_add(psock, sock, tx_msg); bpf_tcp_msg_add(psock, sock, tx_msg);
if (new) { if (new) {
err = tcp_set_ulp_id(sock, TCP_ULP_BPF); err = bpf_tcp_init(sock);
if (err) if (err)
goto out_free; goto out_free;
} }
...@@ -2187,10 +2172,6 @@ static struct bpf_map *sock_hash_alloc(union bpf_attr *attr) ...@@ -2187,10 +2172,6 @@ static struct bpf_map *sock_hash_alloc(union bpf_attr *attr)
*/ */
return ERR_PTR(-E2BIG); return ERR_PTR(-E2BIG);
err = bpf_tcp_ulp_register();
if (err && err != -EEXIST)
return ERR_PTR(err);
htab = kzalloc(sizeof(*htab), GFP_USER); htab = kzalloc(sizeof(*htab), GFP_USER);
if (!htab) if (!htab)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
*/ */
#include<linux/module.h> #include <linux/module.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -29,18 +29,6 @@ static struct tcp_ulp_ops *tcp_ulp_find(const char *name) ...@@ -29,18 +29,6 @@ static struct tcp_ulp_ops *tcp_ulp_find(const char *name)
return NULL; return NULL;
} }
static struct tcp_ulp_ops *tcp_ulp_find_id(const int ulp)
{
struct tcp_ulp_ops *e;
list_for_each_entry_rcu(e, &tcp_ulp_list, list) {
if (e->uid == ulp)
return e;
}
return NULL;
}
static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name) static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name)
{ {
const struct tcp_ulp_ops *ulp = NULL; const struct tcp_ulp_ops *ulp = NULL;
...@@ -63,18 +51,6 @@ static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name) ...@@ -63,18 +51,6 @@ static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name)
return ulp; return ulp;
} }
static const struct tcp_ulp_ops *__tcp_ulp_lookup(const int uid)
{
const struct tcp_ulp_ops *ulp;
rcu_read_lock();
ulp = tcp_ulp_find_id(uid);
if (!ulp || !try_module_get(ulp->owner))
ulp = NULL;
rcu_read_unlock();
return ulp;
}
/* Attach new upper layer protocol to the list /* Attach new upper layer protocol to the list
* of available protocols. * of available protocols.
*/ */
...@@ -135,56 +111,35 @@ void tcp_cleanup_ulp(struct sock *sk) ...@@ -135,56 +111,35 @@ void tcp_cleanup_ulp(struct sock *sk)
icsk->icsk_ulp_ops = NULL; icsk->icsk_ulp_ops = NULL;
} }
/* Change upper layer protocol for socket */ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)
int tcp_set_ulp(struct sock *sk, const char *name)
{ {
struct inet_connection_sock *icsk = inet_csk(sk); struct inet_connection_sock *icsk = inet_csk(sk);
const struct tcp_ulp_ops *ulp_ops; int err;
int err = 0;
sock_owned_by_me(sk); err = -EEXIST;
if (icsk->icsk_ulp_ops) if (icsk->icsk_ulp_ops)
return -EEXIST; goto out_err;
ulp_ops = __tcp_ulp_find_autoload(name);
if (!ulp_ops)
return -ENOENT;
if (!ulp_ops->user_visible) {
module_put(ulp_ops->owner);
return -ENOENT;
}
err = ulp_ops->init(sk); err = ulp_ops->init(sk);
if (err) { if (err)
module_put(ulp_ops->owner); goto out_err;
return err;
}
icsk->icsk_ulp_ops = ulp_ops; icsk->icsk_ulp_ops = ulp_ops;
return 0; return 0;
out_err:
module_put(ulp_ops->owner);
return err;
} }
int tcp_set_ulp_id(struct sock *sk, int ulp) int tcp_set_ulp(struct sock *sk, const char *name)
{ {
struct inet_connection_sock *icsk = inet_csk(sk);
const struct tcp_ulp_ops *ulp_ops; const struct tcp_ulp_ops *ulp_ops;
int err;
sock_owned_by_me(sk); sock_owned_by_me(sk);
if (icsk->icsk_ulp_ops)
return -EEXIST;
ulp_ops = __tcp_ulp_lookup(ulp); ulp_ops = __tcp_ulp_find_autoload(name);
if (!ulp_ops) if (!ulp_ops)
return -ENOENT; return -ENOENT;
err = ulp_ops->init(sk); return __tcp_set_ulp(sk, ulp_ops);
if (err) {
module_put(ulp_ops->owner);
return err;
}
icsk->icsk_ulp_ops = ulp_ops;
return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment