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

bpf: net: Add SO_DETACH_REUSEPORT_BPF

There is SO_ATTACH_REUSEPORT_[CE]BPF but there is no DETACH.
This patch adds SO_DETACH_REUSEPORT_BPF sockopt. The same
sockopt can be used to undo both SO_ATTACH_REUSEPORT_[CE]BPF.

reseport_detach_prog() is added and it is mostly a mirror
of the existing reuseport_attach_prog(). The differences are,
it does not call reuseport_alloc() and returns -ENOENT when
there is no old prog.

Cc: Craig Gallek <kraig@google.com>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Reviewed-by: Stanislav Fomichev <sdf@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

authored by

Martin KaFai Lau and committed by
Daniel Borkmann
99f3a064 e55d54f4

+40
+2
arch/alpha/include/uapi/asm/socket.h
··· 122 122 #define SO_RCVTIMEO_NEW 66 123 123 #define SO_SNDTIMEO_NEW 67 124 124 125 + #define SO_DETACH_REUSEPORT_BPF 68 126 + 125 127 #if !defined(__KERNEL__) 126 128 127 129 #if __BITS_PER_LONG == 64
+2
arch/mips/include/uapi/asm/socket.h
··· 133 133 #define SO_RCVTIMEO_NEW 66 134 134 #define SO_SNDTIMEO_NEW 67 135 135 136 + #define SO_DETACH_REUSEPORT_BPF 68 137 + 136 138 #if !defined(__KERNEL__) 137 139 138 140 #if __BITS_PER_LONG == 64
+2
arch/parisc/include/uapi/asm/socket.h
··· 114 114 #define SO_RCVTIMEO_NEW 0x4040 115 115 #define SO_SNDTIMEO_NEW 0x4041 116 116 117 + #define SO_DETACH_REUSEPORT_BPF 0x4042 118 + 117 119 #if !defined(__KERNEL__) 118 120 119 121 #if __BITS_PER_LONG == 64
+2
arch/sparc/include/uapi/asm/socket.h
··· 115 115 #define SO_RCVTIMEO_NEW 0x0044 116 116 #define SO_SNDTIMEO_NEW 0x0045 117 117 118 + #define SO_DETACH_REUSEPORT_BPF 0x0047 119 + 118 120 #if !defined(__KERNEL__) 119 121 120 122
+2
include/net/sock_reuseport.h
··· 35 35 struct sk_buff *skb, 36 36 int hdr_len); 37 37 extern int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog); 38 + extern int reuseport_detach_prog(struct sock *sk); 39 + 38 40 int reuseport_get_id(struct sock_reuseport *reuse); 39 41 40 42 #endif /* _SOCK_REUSEPORT_H */
+2
include/uapi/asm-generic/socket.h
··· 117 117 #define SO_RCVTIMEO_NEW 66 118 118 #define SO_SNDTIMEO_NEW 67 119 119 120 + #define SO_DETACH_REUSEPORT_BPF 68 121 + 120 122 #if !defined(__KERNEL__) 121 123 122 124 #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
+4
net/core/sock.c
··· 1045 1045 } 1046 1046 break; 1047 1047 1048 + case SO_DETACH_REUSEPORT_BPF: 1049 + ret = reuseport_detach_prog(sk); 1050 + break; 1051 + 1048 1052 case SO_DETACH_FILTER: 1049 1053 ret = sk_detach_filter(sk); 1050 1054 break;
+24
net/core/sock_reuseport.c
··· 332 332 return 0; 333 333 } 334 334 EXPORT_SYMBOL(reuseport_attach_prog); 335 + 336 + int reuseport_detach_prog(struct sock *sk) 337 + { 338 + struct sock_reuseport *reuse; 339 + struct bpf_prog *old_prog; 340 + 341 + if (!rcu_access_pointer(sk->sk_reuseport_cb)) 342 + return sk->sk_reuseport ? -ENOENT : -EINVAL; 343 + 344 + old_prog = NULL; 345 + spin_lock_bh(&reuseport_lock); 346 + reuse = rcu_dereference_protected(sk->sk_reuseport_cb, 347 + lockdep_is_held(&reuseport_lock)); 348 + rcu_swap_protected(reuse->prog, old_prog, 349 + lockdep_is_held(&reuseport_lock)); 350 + spin_unlock_bh(&reuseport_lock); 351 + 352 + if (!old_prog) 353 + return -ENOENT; 354 + 355 + sk_reuseport_prog_free(old_prog); 356 + return 0; 357 + } 358 + EXPORT_SYMBOL(reuseport_detach_prog);