Commit d5305093 authored by Alan Maguire's avatar Alan Maguire Committed by Martin KaFai Lau

selftests/bpf: add sockopt tests for TCP_BPF_SOCK_OPS_CB_FLAGS

Add tests to set TCP sockopt TCP_BPF_SOCK_OPS_CB_FLAGS via
bpf_setsockopt() and use a cgroup/getsockopt program to retrieve
the value to verify it was set.
Signed-off-by: default avatarAlan Maguire <alan.maguire@oracle.com>
Link: https://lore.kernel.org/r/20240808150558.1035626-3-alan.maguire@oracle.comSigned-off-by: default avatarMartin KaFai Lau <martin.lau@kernel.org>
parent 3882dccf
......@@ -154,6 +154,51 @@ static void test_ktls(int family)
close(sfd);
}
static void test_nonstandard_opt(int family)
{
struct setget_sockopt__bss *bss = skel->bss;
struct bpf_link *getsockopt_link = NULL;
int sfd = -1, fd = -1, cfd = -1, flags;
socklen_t flagslen = sizeof(flags);
memset(bss, 0, sizeof(*bss));
sfd = start_server(family, SOCK_STREAM,
family == AF_INET6 ? addr6_str : addr4_str, 0, 0);
if (!ASSERT_GE(sfd, 0, "start_server"))
return;
fd = connect_to_fd(sfd, 0);
if (!ASSERT_GE(fd, 0, "connect_to_fd_server"))
goto err_out;
/* cgroup/getsockopt prog will intercept getsockopt() below and
* retrieve the tcp socket bpf_sock_ops_cb_flags value for the
* accept()ed socket; this was set earlier in the passive established
* callback for the accept()ed socket via bpf_setsockopt().
*/
getsockopt_link = bpf_program__attach_cgroup(skel->progs._getsockopt, cg_fd);
if (!ASSERT_OK_PTR(getsockopt_link, "getsockopt prog"))
goto err_out;
cfd = accept(sfd, NULL, 0);
if (!ASSERT_GE(cfd, 0, "accept"))
goto err_out;
if (!ASSERT_OK(getsockopt(cfd, SOL_TCP, TCP_BPF_SOCK_OPS_CB_FLAGS, &flags, &flagslen),
"getsockopt_flags"))
goto err_out;
ASSERT_EQ(flags & BPF_SOCK_OPS_STATE_CB_FLAG, BPF_SOCK_OPS_STATE_CB_FLAG,
"cb_flags_set");
err_out:
close(sfd);
if (fd != -1)
close(fd);
if (cfd != -1)
close(cfd);
bpf_link__destroy(getsockopt_link);
}
void test_setget_sockopt(void)
{
cg_fd = test__join_cgroup(CG_NAME);
......@@ -191,6 +236,8 @@ void test_setget_sockopt(void)
test_udp(AF_INET);
test_ktls(AF_INET6);
test_ktls(AF_INET);
test_nonstandard_opt(AF_INET);
test_nonstandard_opt(AF_INET6);
done:
setget_sockopt__destroy(skel);
......
......@@ -59,6 +59,8 @@ static const struct sockopt_test sol_tcp_tests[] = {
{ .opt = TCP_THIN_LINEAR_TIMEOUTS, .flip = 1, },
{ .opt = TCP_USER_TIMEOUT, .new = 123400, .expected = 123400, },
{ .opt = TCP_NOTSENT_LOWAT, .new = 1314, .expected = 1314, },
{ .opt = TCP_BPF_SOCK_OPS_CB_FLAGS, .new = BPF_SOCK_OPS_ALL_CB_FLAGS,
.expected = BPF_SOCK_OPS_ALL_CB_FLAGS, },
{ .opt = 0, },
};
......@@ -353,11 +355,30 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family,
return 1;
}
SEC("cgroup/getsockopt")
int _getsockopt(struct bpf_sockopt *ctx)
{
struct bpf_sock *sk = ctx->sk;
int *optval = ctx->optval;
struct tcp_sock *tp;
if (!sk || ctx->level != SOL_TCP || ctx->optname != TCP_BPF_SOCK_OPS_CB_FLAGS)
return 1;
tp = bpf_core_cast(sk, struct tcp_sock);
if (ctx->optval + sizeof(int) <= ctx->optval_end) {
*optval = tp->bpf_sock_ops_cb_flags;
ctx->retval = 0;
}
return 1;
}
SEC("sockops")
int skops_sockopt(struct bpf_sock_ops *skops)
{
struct bpf_sock *bpf_sk = skops->sk;
struct sock *sk;
int flags;
if (!bpf_sk)
return 1;
......@@ -384,9 +405,8 @@ int skops_sockopt(struct bpf_sock_ops *skops)
nr_passive += !(bpf_test_sockopt(skops, sk) ||
test_tcp_maxseg(skops, sk) ||
test_tcp_saved_syn(skops, sk));
bpf_sock_ops_cb_flags_set(skops,
skops->bpf_sock_ops_cb_flags |
BPF_SOCK_OPS_STATE_CB_FLAG);
flags = skops->bpf_sock_ops_cb_flags | BPF_SOCK_OPS_STATE_CB_FLAG;
bpf_setsockopt(skops, SOL_TCP, TCP_BPF_SOCK_OPS_CB_FLAGS, &flags, sizeof(flags));
break;
case BPF_SOCK_OPS_STATE_CB:
if (skops->args[1] == BPF_TCP_CLOSE_WAIT)
......
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