Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Alan Maguire <alan.maguire@oracle.com>
Link: https://lore.kernel.org/r/20240808150558.1035626-3-alan.maguire@oracle.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>

authored by

Alan Maguire and committed by
Martin KaFai Lau
d5305093 3882dccf

+70 -3
+47
tools/testing/selftests/bpf/prog_tests/setget_sockopt.c
··· 154 154 close(sfd); 155 155 } 156 156 157 + static void test_nonstandard_opt(int family) 158 + { 159 + struct setget_sockopt__bss *bss = skel->bss; 160 + struct bpf_link *getsockopt_link = NULL; 161 + int sfd = -1, fd = -1, cfd = -1, flags; 162 + socklen_t flagslen = sizeof(flags); 163 + 164 + memset(bss, 0, sizeof(*bss)); 165 + 166 + sfd = start_server(family, SOCK_STREAM, 167 + family == AF_INET6 ? addr6_str : addr4_str, 0, 0); 168 + if (!ASSERT_GE(sfd, 0, "start_server")) 169 + return; 170 + 171 + fd = connect_to_fd(sfd, 0); 172 + if (!ASSERT_GE(fd, 0, "connect_to_fd_server")) 173 + goto err_out; 174 + 175 + /* cgroup/getsockopt prog will intercept getsockopt() below and 176 + * retrieve the tcp socket bpf_sock_ops_cb_flags value for the 177 + * accept()ed socket; this was set earlier in the passive established 178 + * callback for the accept()ed socket via bpf_setsockopt(). 179 + */ 180 + getsockopt_link = bpf_program__attach_cgroup(skel->progs._getsockopt, cg_fd); 181 + if (!ASSERT_OK_PTR(getsockopt_link, "getsockopt prog")) 182 + goto err_out; 183 + 184 + cfd = accept(sfd, NULL, 0); 185 + if (!ASSERT_GE(cfd, 0, "accept")) 186 + goto err_out; 187 + 188 + if (!ASSERT_OK(getsockopt(cfd, SOL_TCP, TCP_BPF_SOCK_OPS_CB_FLAGS, &flags, &flagslen), 189 + "getsockopt_flags")) 190 + goto err_out; 191 + ASSERT_EQ(flags & BPF_SOCK_OPS_STATE_CB_FLAG, BPF_SOCK_OPS_STATE_CB_FLAG, 192 + "cb_flags_set"); 193 + err_out: 194 + close(sfd); 195 + if (fd != -1) 196 + close(fd); 197 + if (cfd != -1) 198 + close(cfd); 199 + bpf_link__destroy(getsockopt_link); 200 + } 201 + 157 202 void test_setget_sockopt(void) 158 203 { 159 204 cg_fd = test__join_cgroup(CG_NAME); ··· 236 191 test_udp(AF_INET); 237 192 test_ktls(AF_INET6); 238 193 test_ktls(AF_INET); 194 + test_nonstandard_opt(AF_INET); 195 + test_nonstandard_opt(AF_INET6); 239 196 240 197 done: 241 198 setget_sockopt__destroy(skel);
+23 -3
tools/testing/selftests/bpf/progs/setget_sockopt.c
··· 59 59 { .opt = TCP_THIN_LINEAR_TIMEOUTS, .flip = 1, }, 60 60 { .opt = TCP_USER_TIMEOUT, .new = 123400, .expected = 123400, }, 61 61 { .opt = TCP_NOTSENT_LOWAT, .new = 1314, .expected = 1314, }, 62 + { .opt = TCP_BPF_SOCK_OPS_CB_FLAGS, .new = BPF_SOCK_OPS_ALL_CB_FLAGS, 63 + .expected = BPF_SOCK_OPS_ALL_CB_FLAGS, }, 62 64 { .opt = 0, }, 63 65 }; 64 66 ··· 355 353 return 1; 356 354 } 357 355 356 + SEC("cgroup/getsockopt") 357 + int _getsockopt(struct bpf_sockopt *ctx) 358 + { 359 + struct bpf_sock *sk = ctx->sk; 360 + int *optval = ctx->optval; 361 + struct tcp_sock *tp; 362 + 363 + if (!sk || ctx->level != SOL_TCP || ctx->optname != TCP_BPF_SOCK_OPS_CB_FLAGS) 364 + return 1; 365 + 366 + tp = bpf_core_cast(sk, struct tcp_sock); 367 + if (ctx->optval + sizeof(int) <= ctx->optval_end) { 368 + *optval = tp->bpf_sock_ops_cb_flags; 369 + ctx->retval = 0; 370 + } 371 + return 1; 372 + } 373 + 358 374 SEC("sockops") 359 375 int skops_sockopt(struct bpf_sock_ops *skops) 360 376 { 361 377 struct bpf_sock *bpf_sk = skops->sk; 362 378 struct sock *sk; 379 + int flags; 363 380 364 381 if (!bpf_sk) 365 382 return 1; ··· 405 384 nr_passive += !(bpf_test_sockopt(skops, sk) || 406 385 test_tcp_maxseg(skops, sk) || 407 386 test_tcp_saved_syn(skops, sk)); 408 - bpf_sock_ops_cb_flags_set(skops, 409 - skops->bpf_sock_ops_cb_flags | 410 - BPF_SOCK_OPS_STATE_CB_FLAG); 387 + flags = skops->bpf_sock_ops_cb_flags | BPF_SOCK_OPS_STATE_CB_FLAG; 388 + bpf_setsockopt(skops, SOL_TCP, TCP_BPF_SOCK_OPS_CB_FLAGS, &flags, sizeof(flags)); 411 389 break; 412 390 case BPF_SOCK_OPS_STATE_CB: 413 391 if (skops->args[1] == BPF_TCP_CLOSE_WAIT)