Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Add sockmap hooks for UDP sockets

Add basic psock hooks for UDP sockets. This allows adding and
removing sockets, as well as automatic removal on unhash and close.

Signed-off-by: Lorenz Bauer <lmb@cloudflare.com>
Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/bpf/20200309111243.6982-8-lmb@cloudflare.com

authored by

Lorenz Bauer and committed by
Daniel Borkmann
edc6741c cb21802b

+60
+1
MAINTAINERS
··· 9370 9370 F: net/core/skmsg.c 9371 9371 F: net/core/sock_map.c 9372 9372 F: net/ipv4/tcp_bpf.c 9373 + F: net/ipv4/udp_bpf.c 9373 9374 9374 9375 LANTIQ / INTEL Ethernet drivers 9375 9376 M: Hauke Mehrtens <hauke@hauke-m.de>
+5
include/net/udp.h
··· 503 503 return segs; 504 504 } 505 505 506 + #ifdef CONFIG_BPF_STREAM_PARSER 507 + struct sk_psock; 508 + struct proto *udp_bpf_get_proto(struct sock *sk, struct sk_psock *psock); 509 + #endif /* BPF_STREAM_PARSER */ 510 + 506 511 #endif /* _UDP_H */
+1
net/ipv4/Makefile
··· 61 61 obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o 62 62 obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o 63 63 obj-$(CONFIG_NET_SOCK_MSG) += tcp_bpf.o 64 + obj-$(CONFIG_BPF_STREAM_PARSER) += udp_bpf.o 64 65 obj-$(CONFIG_NETLABEL) += cipso_ipv4.o 65 66 66 67 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
+53
net/ipv4/udp_bpf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2020 Cloudflare Ltd https://cloudflare.com */ 3 + 4 + #include <linux/skmsg.h> 5 + #include <net/sock.h> 6 + #include <net/udp.h> 7 + 8 + enum { 9 + UDP_BPF_IPV4, 10 + UDP_BPF_IPV6, 11 + UDP_BPF_NUM_PROTS, 12 + }; 13 + 14 + static struct proto *udpv6_prot_saved __read_mostly; 15 + static DEFINE_SPINLOCK(udpv6_prot_lock); 16 + static struct proto udp_bpf_prots[UDP_BPF_NUM_PROTS]; 17 + 18 + static void udp_bpf_rebuild_protos(struct proto *prot, const struct proto *base) 19 + { 20 + *prot = *base; 21 + prot->unhash = sock_map_unhash; 22 + prot->close = sock_map_close; 23 + } 24 + 25 + static void udp_bpf_check_v6_needs_rebuild(struct sock *sk, struct proto *ops) 26 + { 27 + if (sk->sk_family == AF_INET6 && 28 + unlikely(ops != smp_load_acquire(&udpv6_prot_saved))) { 29 + spin_lock_bh(&udpv6_prot_lock); 30 + if (likely(ops != udpv6_prot_saved)) { 31 + udp_bpf_rebuild_protos(&udp_bpf_prots[UDP_BPF_IPV6], ops); 32 + smp_store_release(&udpv6_prot_saved, ops); 33 + } 34 + spin_unlock_bh(&udpv6_prot_lock); 35 + } 36 + } 37 + 38 + static int __init udp_bpf_v4_build_proto(void) 39 + { 40 + udp_bpf_rebuild_protos(&udp_bpf_prots[UDP_BPF_IPV4], &udp_prot); 41 + return 0; 42 + } 43 + core_initcall(udp_bpf_v4_build_proto); 44 + 45 + struct proto *udp_bpf_get_proto(struct sock *sk, struct sk_psock *psock) 46 + { 47 + int family = sk->sk_family == AF_INET ? UDP_BPF_IPV4 : UDP_BPF_IPV6; 48 + 49 + if (!psock->sk_proto) 50 + udp_bpf_check_v6_needs_rebuild(sk, READ_ONCE(sk->sk_prot)); 51 + 52 + return &udp_bpf_prots[family]; 53 + }