On Tue, Feb 25, 2020 at 02:56 PM CET, Lorenz Bauer wrote: > The sockmap works by overriding some of the callbacks in sk->sk_prot, while > leaving others untouched. This means that we need access to the struct proto > for any protocol we want to support. For IPv4 this is trivial, since both > TCP and UDP are always compiled in. IPv6 may be disabled or compiled as a > module, so the existing TCP sockmap hooks use some trickery to lazily > initialize the modified struct proto for TCPv6. > > Pull this logic into a standalone struct sk_psock_hooks, so that it can be > re-used by UDP sockmap. > > Signed-off-by: Lorenz Bauer <lmb@xxxxxxxxxxxxxx> > --- > include/linux/skmsg.h | 36 ++++++++----- > include/net/tcp.h | 1 - > net/core/skmsg.c | 52 +++++++++++++++++++ > net/core/sock_map.c | 24 ++++----- > net/ipv4/tcp_bpf.c | 114 ++++++++++++------------------------------ > 5 files changed, 116 insertions(+), 111 deletions(-) > [...] > diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c > index 90955c96a9a8..81c0431a8dbd 100644 > --- a/net/ipv4/tcp_bpf.c > +++ b/net/ipv4/tcp_bpf.c [...] > @@ -650,9 +599,10 @@ int tcp_bpf_init(struct sock *sk) > */ > void tcp_bpf_clone(const struct sock *sk, struct sock *newsk) > { > - int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4; > - struct proto *prot = newsk->sk_prot; > + struct proto *prot = READ_ONCE(sk->sk_prot); For the sake of keeping the review open - we've identified a regression here. sk->sk_prot can change by the time we get here, since the moment we copied the listener sock. We need to stick to checking newsk->sk_prot here. > > - if (prot == &tcp_bpf_prots[family][TCP_BPF_BASE]) > + /* TCP_LISTEN can only use TCP_BPF_BASE, so this is safe */ > + if (unlikely(prot == &tcp_bpf_ipv4[TCP_BPF_BASE] || > + prot == &tcp_bpf_ipv6[TCP_BPF_BASE])) > newsk->sk_prot = sk->sk_prot_creator; > }