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>
#define SO_RCVTIMEO_NEW 66
#define SO_SNDTIMEO_NEW 67
+#define SO_DETACH_REUSEPORT_BPF 68
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
#define SO_RCVTIMEO_NEW 66
#define SO_SNDTIMEO_NEW 67
+#define SO_DETACH_REUSEPORT_BPF 68
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
#define SO_RCVTIMEO_NEW 0x4040
#define SO_SNDTIMEO_NEW 0x4041
+#define SO_DETACH_REUSEPORT_BPF 0x4042
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
#define SO_RCVTIMEO_NEW 0x0044
#define SO_SNDTIMEO_NEW 0x0045
+#define SO_DETACH_REUSEPORT_BPF 0x0047
+
#if !defined(__KERNEL__)
struct sk_buff *skb,
int hdr_len);
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);
#endif /* _SOCK_REUSEPORT_H */
#define SO_RCVTIMEO_NEW 66
#define SO_SNDTIMEO_NEW 67
+#define SO_DETACH_REUSEPORT_BPF 68
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
}
break;
+ case SO_DETACH_REUSEPORT_BPF:
+ ret = reuseport_detach_prog(sk);
+ break;
+
case SO_DETACH_FILTER:
ret = sk_detach_filter(sk);
break;
return 0;
}
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);