Commit 99f3a064 authored by Martin KaFai Lau's avatar Martin KaFai Lau Committed by Daniel Borkmann

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: default avatarMartin KaFai Lau <kafai@fb.com>
Reviewed-by: default avatarStanislav Fomichev <sdf@google.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent e55d54f4
...@@ -122,6 +122,8 @@ ...@@ -122,6 +122,8 @@
#define SO_RCVTIMEO_NEW 66 #define SO_RCVTIMEO_NEW 66
#define SO_SNDTIMEO_NEW 67 #define SO_SNDTIMEO_NEW 67
#define SO_DETACH_REUSEPORT_BPF 68
#if !defined(__KERNEL__) #if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 #if __BITS_PER_LONG == 64
......
...@@ -133,6 +133,8 @@ ...@@ -133,6 +133,8 @@
#define SO_RCVTIMEO_NEW 66 #define SO_RCVTIMEO_NEW 66
#define SO_SNDTIMEO_NEW 67 #define SO_SNDTIMEO_NEW 67
#define SO_DETACH_REUSEPORT_BPF 68
#if !defined(__KERNEL__) #if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 #if __BITS_PER_LONG == 64
......
...@@ -114,6 +114,8 @@ ...@@ -114,6 +114,8 @@
#define SO_RCVTIMEO_NEW 0x4040 #define SO_RCVTIMEO_NEW 0x4040
#define SO_SNDTIMEO_NEW 0x4041 #define SO_SNDTIMEO_NEW 0x4041
#define SO_DETACH_REUSEPORT_BPF 0x4042
#if !defined(__KERNEL__) #if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 #if __BITS_PER_LONG == 64
......
...@@ -115,6 +115,8 @@ ...@@ -115,6 +115,8 @@
#define SO_RCVTIMEO_NEW 0x0044 #define SO_RCVTIMEO_NEW 0x0044
#define SO_SNDTIMEO_NEW 0x0045 #define SO_SNDTIMEO_NEW 0x0045
#define SO_DETACH_REUSEPORT_BPF 0x0047
#if !defined(__KERNEL__) #if !defined(__KERNEL__)
......
...@@ -35,6 +35,8 @@ extern struct sock *reuseport_select_sock(struct sock *sk, ...@@ -35,6 +35,8 @@ extern struct sock *reuseport_select_sock(struct sock *sk,
struct sk_buff *skb, struct sk_buff *skb,
int hdr_len); int hdr_len);
extern int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog); extern int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog);
extern int reuseport_detach_prog(struct sock *sk);
int reuseport_get_id(struct sock_reuseport *reuse); int reuseport_get_id(struct sock_reuseport *reuse);
#endif /* _SOCK_REUSEPORT_H */ #endif /* _SOCK_REUSEPORT_H */
...@@ -117,6 +117,8 @@ ...@@ -117,6 +117,8 @@
#define SO_RCVTIMEO_NEW 66 #define SO_RCVTIMEO_NEW 66
#define SO_SNDTIMEO_NEW 67 #define SO_SNDTIMEO_NEW 67
#define SO_DETACH_REUSEPORT_BPF 68
#if !defined(__KERNEL__) #if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__)) #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
......
...@@ -1045,6 +1045,10 @@ int sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1045,6 +1045,10 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
} }
break; break;
case SO_DETACH_REUSEPORT_BPF:
ret = reuseport_detach_prog(sk);
break;
case SO_DETACH_FILTER: case SO_DETACH_FILTER:
ret = sk_detach_filter(sk); ret = sk_detach_filter(sk);
break; break;
......
...@@ -332,3 +332,27 @@ int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog) ...@@ -332,3 +332,27 @@ int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog)
return 0; return 0;
} }
EXPORT_SYMBOL(reuseport_attach_prog); EXPORT_SYMBOL(reuseport_attach_prog);
int reuseport_detach_prog(struct sock *sk)
{
struct sock_reuseport *reuse;
struct bpf_prog *old_prog;
if (!rcu_access_pointer(sk->sk_reuseport_cb))
return sk->sk_reuseport ? -ENOENT : -EINVAL;
old_prog = NULL;
spin_lock_bh(&reuseport_lock);
reuse = rcu_dereference_protected(sk->sk_reuseport_cb,
lockdep_is_held(&reuseport_lock));
rcu_swap_protected(reuse->prog, old_prog,
lockdep_is_held(&reuseport_lock));
spin_unlock_bh(&reuseport_lock);
if (!old_prog)
return -ENOENT;
sk_reuseport_prog_free(old_prog);
return 0;
}
EXPORT_SYMBOL(reuseport_detach_prog);
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