bpf: Refactor bpf_setsockopt(TCP_CONGESTION) handling into another function

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>
This commit is contained in:
Martin KaFai Lau 2022-09-29 00:04:05 -07:00 committed by Alexei Starovoitov
parent 37cfbe0bf2
commit 1e7d217faa

View 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));