bpf: Refactor bpf_setsockopt(TCP_CONGESTION) handling into another function
authorMartin KaFai Lau <martin.lau@kernel.org>
Thu, 29 Sep 2022 07:04:05 +0000 (00:04 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 29 Sep 2022 16:25:47 +0000 (09:25 -0700)
This patch moves the bpf_setsockopt(TCP_CONGESTION) logic into
another function.  The next patch will add extra logic to avoid
recursion and this will make the latter patch easier to follow.

Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://lore.kernel.org/r/20220929070407.965581-4-martin.lau@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
net/core/filter.c

index f4cea3f..96f2f7a 100644 (file)
@@ -5102,6 +5102,33 @@ static int bpf_sol_tcp_setsockopt(struct sock *sk, int optname,
        return 0;
 }
 
+static int sol_tcp_sockopt_congestion(struct sock *sk, char *optval,
+                                     int *optlen, bool getopt)
+{
+       if (*optlen < 2)
+               return -EINVAL;
+
+       if (getopt) {
+               if (!inet_csk(sk)->icsk_ca_ops)
+                       return -EINVAL;
+               /* BPF expects NULL-terminated tcp-cc string */
+               optval[--(*optlen)] = '\0';
+               return do_tcp_getsockopt(sk, SOL_TCP, TCP_CONGESTION,
+                                        KERNEL_SOCKPTR(optval),
+                                        KERNEL_SOCKPTR(optlen));
+       }
+
+       /* "cdg" is the only cc that alloc a ptr
+        * in inet_csk_ca area.  The bpf-tcp-cc may
+        * overwrite this ptr after switching to cdg.
+        */
+       if (*optlen >= sizeof("cdg") - 1 && !strncmp("cdg", optval, *optlen))
+               return -ENOTSUPP;
+
+       return do_tcp_setsockopt(sk, SOL_TCP, TCP_CONGESTION,
+                               KERNEL_SOCKPTR(optval), *optlen);
+}
+
 static int sol_tcp_sockopt(struct sock *sk, int optname,
                           char *optval, int *optlen,
                           bool getopt)
@@ -5125,16 +5152,7 @@ static int sol_tcp_sockopt(struct sock *sk, int optname,
                        return -EINVAL;
                break;
        case TCP_CONGESTION:
-               if (*optlen < 2)
-                       return -EINVAL;
-               /* "cdg" is the only cc that alloc a ptr
-                * in inet_csk_ca area.  The bpf-tcp-cc may
-                * overwrite this ptr after switching to cdg.
-                */
-               if (!getopt && *optlen >= sizeof("cdg") - 1 &&
-                   !strncmp("cdg", optval, *optlen))
-                       return -ENOTSUPP;
-               break;
+               return sol_tcp_sockopt_congestion(sk, optval, optlen, getopt);
        case TCP_SAVED_SYN:
                if (*optlen < 1)
                        return -EINVAL;
@@ -5159,13 +5177,6 @@ static int sol_tcp_sockopt(struct sock *sk, int optname,
                        return 0;
                }
 
-               if (optname == TCP_CONGESTION) {
-                       if (!inet_csk(sk)->icsk_ca_ops)
-                               return -EINVAL;
-                       /* BPF expects NULL-terminated tcp-cc string */
-                       optval[--(*optlen)] = '\0';
-               }
-
                return do_tcp_getsockopt(sk, SOL_TCP, optname,
                                         KERNEL_SOCKPTR(optval),
                                         KERNEL_SOCKPTR(optlen));