bpf: Add getter and setter for SO_REUSEPORT through bpf_{g,s}etsockopt
authorManu Bretelle <chantra@fb.com>
Wed, 10 Mar 2021 18:23:05 +0000 (10:23 -0800)
committerDaniel Borkmann <daniel@iogearbox.net>
Mon, 15 Mar 2021 16:22:22 +0000 (17:22 +0100)
Augment the current set of options that are accessible via
bpf_{g,s}etsockopt to also support SO_REUSEPORT.

Signed-off-by: Manu Bretelle <chantra@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Link: https://lore.kernel.org/bpf/20210310182305.1910312-1-chantra@fb.com
net/core/filter.c
tools/testing/selftests/bpf/progs/bind4_prog.c
tools/testing/selftests/bpf/progs/bind6_prog.c

index b673200..10dac9d 100644 (file)
@@ -4729,6 +4729,9 @@ static int _bpf_setsockopt(struct sock *sk, int level, int optname,
                                sk->sk_prot->keepalive(sk, valbool);
                        sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
                        break;
+               case SO_REUSEPORT:
+                       sk->sk_reuseport = valbool;
+                       break;
                default:
                        ret = -EINVAL;
                }
@@ -4898,6 +4901,9 @@ static int _bpf_getsockopt(struct sock *sk, int level, int optname,
                case SO_BINDTOIFINDEX:
                        *((int *)optval) = sk->sk_bound_dev_if;
                        break;
+               case SO_REUSEPORT:
+                       *((int *)optval) = sk->sk_reuseport;
+                       break;
                default:
                        goto err_clear;
                }
index 115a3b0..474c6a6 100644 (file)
@@ -57,6 +57,27 @@ static __inline int bind_to_device(struct bpf_sock_addr *ctx)
        return 0;
 }
 
+static __inline int bind_reuseport(struct bpf_sock_addr *ctx)
+{
+       int val = 1;
+
+       if (bpf_setsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
+                          &val, sizeof(val)))
+               return 1;
+       if (bpf_getsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
+                          &val, sizeof(val)) || !val)
+               return 1;
+       val = 0;
+       if (bpf_setsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
+                          &val, sizeof(val)))
+               return 1;
+       if (bpf_getsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
+                          &val, sizeof(val)) || val)
+               return 1;
+
+       return 0;
+}
+
 static __inline int misc_opts(struct bpf_sock_addr *ctx, int opt)
 {
        int old, tmp, new = 0xeb9f;
@@ -127,6 +148,10 @@ int bind_v4_prog(struct bpf_sock_addr *ctx)
        if (misc_opts(ctx, SO_MARK) || misc_opts(ctx, SO_PRIORITY))
                return 0;
 
+       /* Set reuseport and unset */
+       if (bind_reuseport(ctx))
+               return 0;
+
        ctx->user_ip4 = bpf_htonl(SERV4_REWRITE_IP);
        ctx->user_port = bpf_htons(SERV4_REWRITE_PORT);
 
index 4c0d348..c19cfa8 100644 (file)
@@ -63,6 +63,27 @@ static __inline int bind_to_device(struct bpf_sock_addr *ctx)
        return 0;
 }
 
+static __inline int bind_reuseport(struct bpf_sock_addr *ctx)
+{
+       int val = 1;
+
+       if (bpf_setsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
+                          &val, sizeof(val)))
+               return 1;
+       if (bpf_getsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
+                          &val, sizeof(val)) || !val)
+               return 1;
+       val = 0;
+       if (bpf_setsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
+                          &val, sizeof(val)))
+               return 1;
+       if (bpf_getsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
+                          &val, sizeof(val)) || val)
+               return 1;
+
+       return 0;
+}
+
 static __inline int misc_opts(struct bpf_sock_addr *ctx, int opt)
 {
        int old, tmp, new = 0xeb9f;
@@ -141,6 +162,10 @@ int bind_v6_prog(struct bpf_sock_addr *ctx)
        if (misc_opts(ctx, SO_MARK) || misc_opts(ctx, SO_PRIORITY))
                return 0;
 
+       /* Set reuseport and unset */
+       if (bind_reuseport(ctx))
+               return 0;
+
        ctx->user_ip6[0] = bpf_htonl(SERV6_REWRITE_IP_0);
        ctx->user_ip6[1] = bpf_htonl(SERV6_REWRITE_IP_1);
        ctx->user_ip6[2] = bpf_htonl(SERV6_REWRITE_IP_2);