Context |
Check |
Description |
netdev/series_format |
success
|
Posting correctly formatted
|
netdev/tree_selection |
success
|
Clearly marked for bpf-next, async
|
netdev/ynl |
success
|
Generated files up to date;
no warnings/errors;
no diff in generated;
|
netdev/fixes_present |
success
|
Fixes tag not required for -next series
|
netdev/header_inline |
success
|
No static functions without inline keyword in header files
|
netdev/build_32bit |
success
|
Errors and warnings before: 7 this patch: 7
|
netdev/build_tools |
success
|
Errors and warnings before: 10 this patch: 10
|
netdev/cc_maintainers |
warning
|
6 maintainers not CCed: linux-kselftest@vger.kernel.org shuah@kernel.org mykolal@fb.com tony.ambardar@gmail.com geliang@kernel.org andrii@kernel.org
|
netdev/build_clang |
success
|
Errors and warnings before: 7 this patch: 7
|
netdev/verify_signedoff |
success
|
Signed-off-by tag matches author and committer
|
netdev/deprecated_api |
success
|
None detected
|
netdev/check_selftest |
success
|
No net selftest shell script
|
netdev/verify_fixes |
success
|
No Fixes tag
|
netdev/build_allmodconfig_warn |
success
|
Errors and warnings before: 7 this patch: 7
|
netdev/checkpatch |
warning
|
WARNING: line length of 81 exceeds 80 columns
WARNING: line length of 82 exceeds 80 columns
WARNING: line length of 86 exceeds 80 columns
WARNING: line length of 88 exceeds 80 columns
WARNING: line length of 94 exceeds 80 columns
WARNING: line length of 99 exceeds 80 columns
|
netdev/build_clang_rust |
success
|
No Rust files in patch. Skipping build
|
netdev/kdoc |
success
|
Errors and warnings before: 0 this patch: 0
|
netdev/source_inline |
success
|
Was 0 now: 0
|
bpf/vmtest-bpf-next-VM_Test-0 |
success
|
Logs for Lint
|
bpf/vmtest-bpf-next-VM_Test-1 |
success
|
Logs for ShellCheck
|
bpf/vmtest-bpf-next-VM_Test-2 |
success
|
Logs for Unittests
|
bpf/vmtest-bpf-next-VM_Test-3 |
success
|
Logs for Validate matrix.py
|
bpf/vmtest-bpf-next-VM_Test-5 |
success
|
Logs for aarch64-gcc / build-release
|
bpf/vmtest-bpf-next-VM_Test-10 |
success
|
Logs for aarch64-gcc / veristat
|
bpf/vmtest-bpf-next-VM_Test-12 |
success
|
Logs for s390x-gcc / build-release
|
bpf/vmtest-bpf-next-VM_Test-4 |
success
|
Logs for aarch64-gcc / build / build for aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-35 |
success
|
Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-34 |
success
|
Logs for x86_64-llvm-17 / veristat
|
bpf/vmtest-bpf-next-VM_Test-36 |
success
|
Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
|
bpf/vmtest-bpf-next-VM_Test-11 |
success
|
Logs for s390x-gcc / build / build for s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-19 |
success
|
Logs for x86_64-gcc / build / build for x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-17 |
success
|
Logs for s390x-gcc / veristat
|
bpf/vmtest-bpf-next-VM_Test-18 |
success
|
Logs for set-matrix
|
bpf/vmtest-bpf-next-VM_Test-20 |
success
|
Logs for x86_64-gcc / build-release
|
bpf/vmtest-bpf-next-VM_Test-29 |
success
|
Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
|
bpf/vmtest-bpf-next-VM_Test-42 |
success
|
Logs for x86_64-llvm-18 / veristat
|
bpf/vmtest-bpf-next-VM_Test-28 |
success
|
Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-6 |
success
|
Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-9 |
success
|
Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-13 |
success
|
Logs for s390x-gcc / test (test_maps, false, 360) / test_maps on s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-16 |
success
|
Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-33 |
success
|
Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-23 |
fail
|
Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-15 |
fail
|
Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-26 |
success
|
Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-25 |
success
|
Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-7 |
fail
|
Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-14 |
fail
|
Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-21 |
success
|
Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-27 |
success
|
Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-22 |
fail
|
Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-8 |
fail
|
Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-24 |
success
|
Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-41 |
success
|
Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-PR |
fail
|
PR summary
|
bpf/vmtest-bpf-next-VM_Test-32 |
fail
|
Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-30 |
success
|
Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-31 |
fail
|
Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-37 |
success
|
Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-38 |
fail
|
Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-39 |
fail
|
Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-40 |
fail
|
Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
|
@@ -4,10 +4,13 @@
#include <sched.h>
#include <test_progs.h>
#include "network_helpers.h"
+#include "cgroup_helpers.h"
#include "bpf_dctcp.skel.h"
#include "bpf_cubic.skel.h"
#include "bpf_iter_setsockopt.skel.h"
+#define TEST_CGROUP "/test-iter-setsockopt"
+
static int create_netns(void)
{
if (!ASSERT_OK(unshare(CLONE_NEWNET), "create netns"))
@@ -32,17 +35,26 @@ static unsigned int set_bpf_cubic(int *fds, unsigned int nr_fds)
return nr_fds;
}
-static unsigned int check_bpf_dctcp(int *fds, unsigned int nr_fds)
+static unsigned int check_bpf_val(int *fds, unsigned int nr_fds, bool cong)
{
char tcp_cc[16];
- socklen_t optlen = sizeof(tcp_cc);
+ socklen_t cc_optlen = sizeof(tcp_cc);
+ int flags;
+ socklen_t flags_optlen = sizeof(flags);
unsigned int i;
for (i = 0; i < nr_fds; i++) {
- if (getsockopt(fds[i], SOL_TCP, TCP_CONGESTION,
- tcp_cc, &optlen) ||
- strcmp(tcp_cc, "bpf_dctcp"))
- return i;
+ if (cong) {
+ if (getsockopt(fds[i], SOL_TCP, TCP_CONGESTION,
+ tcp_cc, &cc_optlen) ||
+ strcmp(tcp_cc, "bpf_dctcp"))
+ return i;
+ } else {
+ if (getsockopt(fds[i], SOL_TCP, TCP_BPF_SOCK_OPS_CB_FLAGS,
+ &flags, &flags_optlen) ||
+ flags != BPF_SOCK_OPS_ALL_CB_FLAGS)
+ return i;
+ }
}
return nr_fds;
@@ -102,7 +114,7 @@ static unsigned short get_local_port(int fd)
}
static void do_bpf_iter_setsockopt(struct bpf_iter_setsockopt *iter_skel,
- bool random_retry)
+ bool random_retry, bool cong)
{
int *reuse_listen_fds = NULL, *accepted_fds = NULL, *est_fds = NULL;
unsigned int nr_reuse_listens = 256, nr_est = 256;
@@ -140,9 +152,16 @@ static void do_bpf_iter_setsockopt(struct bpf_iter_setsockopt *iter_skel,
"get_local_port(reuse_listen_fds[0])"))
goto done;
- /* Run bpf tcp iter to switch from bpf_cubic to bpf_dctcp */
+ /* Run bpf tcp iter to change tcp value:
+ *
+ * - If cong is true, switch from bpf_cubic to bpf_dctcp;
+ * - If cong is false, use bpf_setsockopt() to set TCP sockops flags.
+ */
+
iter_skel->bss->random_retry = random_retry;
- iter_fd = bpf_iter_create(bpf_link__fd(iter_skel->links.change_tcp_cc));
+ iter_skel->bss->cong = cong;
+
+ iter_fd = bpf_iter_create(bpf_link__fd(iter_skel->links.change_tcp_val));
if (!ASSERT_GE(iter_fd, 0, "create iter_fd"))
goto done;
@@ -152,22 +171,21 @@ static void do_bpf_iter_setsockopt(struct bpf_iter_setsockopt *iter_skel,
if (!ASSERT_OK(err, "read iter error"))
goto done;
- /* Check reuseport listen fds for dctcp */
- ASSERT_EQ(check_bpf_dctcp(reuse_listen_fds, nr_reuse_listens),
+ /* Check reuseport listen fds */
+ ASSERT_EQ(check_bpf_val(reuse_listen_fds, nr_reuse_listens, cong),
nr_reuse_listens,
- "check reuse_listen_fds dctcp");
-
- /* Check non reuseport listen fd for dctcp */
- ASSERT_EQ(check_bpf_dctcp(&listen_fd, 1), 1,
- "check listen_fd dctcp");
+ "check reuse_listen_fds");
+ /* Check non reuseport listen fd */
+ ASSERT_EQ(check_bpf_val(&listen_fd, 1, cong), 1,
+ "check listen_fd");
- /* Check established fds for dctcp */
- ASSERT_EQ(check_bpf_dctcp(est_fds, nr_est), nr_est,
- "check est_fds dctcp");
+ /* Check established fds */
+ ASSERT_EQ(check_bpf_val(est_fds, nr_est, cong), nr_est,
+ "check est_fds");
- /* Check accepted fds for dctcp */
- ASSERT_EQ(check_bpf_dctcp(accepted_fds, nr_est), nr_est,
- "check accepted_fds dctcp");
+ /* Check accepted fds */
+ ASSERT_EQ(check_bpf_val(accepted_fds, nr_est, cong), nr_est,
+ "check accepted_fds");
done:
if (iter_fd != -1)
@@ -186,6 +204,8 @@ void serial_test_bpf_iter_setsockopt(void)
struct bpf_dctcp *dctcp_skel = NULL;
struct bpf_link *cubic_link = NULL;
struct bpf_link *dctcp_link = NULL;
+ struct bpf_link *getsockopt_link = NULL;
+ int cgroup_fd;
if (create_netns())
return;
@@ -194,8 +214,9 @@ void serial_test_bpf_iter_setsockopt(void)
iter_skel = bpf_iter_setsockopt__open_and_load();
if (!ASSERT_OK_PTR(iter_skel, "iter_skel"))
return;
- iter_skel->links.change_tcp_cc = bpf_program__attach_iter(iter_skel->progs.change_tcp_cc, NULL);
- if (!ASSERT_OK_PTR(iter_skel->links.change_tcp_cc, "attach iter"))
+ iter_skel->links.change_tcp_val = bpf_program__attach_iter(iter_skel->progs.change_tcp_val,
+ NULL);
+ if (!ASSERT_OK_PTR(iter_skel->links.change_tcp_val, "attach iter"))
goto done;
/* Load bpf_cubic */
@@ -214,13 +235,23 @@ void serial_test_bpf_iter_setsockopt(void)
if (!ASSERT_OK_PTR(dctcp_link, "dctcp_link"))
goto done;
- do_bpf_iter_setsockopt(iter_skel, true);
- do_bpf_iter_setsockopt(iter_skel, false);
+ cgroup_fd = cgroup_setup_and_join(TEST_CGROUP);
+ if (!ASSERT_OK_FD(cgroup_fd, "cgroup switch"))
+ goto done;
+ getsockopt_link = bpf_program__attach_cgroup(iter_skel->progs._getsockopt, cgroup_fd);
+ if (!ASSERT_OK_PTR(getsockopt_link, "getsockopt prog"))
+ goto done;
+ do_bpf_iter_setsockopt(iter_skel, true, true);
+ do_bpf_iter_setsockopt(iter_skel, false, true);
+ do_bpf_iter_setsockopt(iter_skel, true, false);
+ do_bpf_iter_setsockopt(iter_skel, false, false);
done:
bpf_link__destroy(cubic_link);
bpf_link__destroy(dctcp_link);
+ bpf_link__destroy(getsockopt_link);
bpf_cubic__destroy(cubic_skel);
bpf_dctcp__destroy(dctcp_skel);
bpf_iter_setsockopt__destroy(iter_skel);
+ cleanup_cgroup_environment();
}
@@ -5,6 +5,13 @@
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>
+struct {
+ __uint(type, BPF_MAP_TYPE_SK_STORAGE);
+ __uint(map_flags, BPF_F_NO_PREALLOC);
+ __type(key, int);
+ __type(value, int);
+} sk_map SEC(".maps");
+
#define bpf_tcp_sk(skc) ({ \
struct sock_common *_skc = skc; \
sk = NULL; \
@@ -21,6 +28,7 @@ unsigned short listen_hport = 0;
char cubic_cc[TCP_CA_NAME_MAX] = "bpf_cubic";
char dctcp_cc[TCP_CA_NAME_MAX] = "bpf_dctcp";
bool random_retry = false;
+bool cong = false;
static bool tcp_cc_eq(const char *a, const char *b)
{
@@ -36,10 +44,32 @@ static bool tcp_cc_eq(const char *a, const char *b)
return true;
}
+/* This program is used to intercept getsockopt() calls, providing
+ * the value of bpf_sock_ops_cb_flags for the socket; this value
+ * has been saved in per-socket storage earlier via the iterator
+ * program.
+ */
+SEC("cgroup/getsockopt")
+int _getsockopt(struct bpf_sockopt *ctx)
+{
+ struct bpf_sock *sk = ctx->sk;
+ int *optval = ctx->optval;
+ int *sk_storage = 0;
+
+ if (!sk || ctx->level != SOL_TCP || ctx->optname != TCP_BPF_SOCK_OPS_CB_FLAGS)
+ return 1;
+ sk_storage = bpf_sk_storage_get(&sk_map, sk, 0, 0);
+ if (sk_storage) {
+ if (ctx->optval + sizeof(int) <= ctx->optval_end)
+ *optval = *sk_storage;
+ ctx->retval = 0;
+ }
+ return 1;
+}
+
SEC("iter/tcp")
-int change_tcp_cc(struct bpf_iter__tcp *ctx)
+int change_tcp_val(struct bpf_iter__tcp *ctx)
{
- char cur_cc[TCP_CA_NAME_MAX];
struct tcp_sock *tp;
struct sock *sk;
@@ -54,17 +84,43 @@ int change_tcp_cc(struct bpf_iter__tcp *ctx)
bpf_ntohs(sk->sk_dport) != listen_hport))
return 0;
- if (bpf_getsockopt(tp, SOL_TCP, TCP_CONGESTION,
- cur_cc, sizeof(cur_cc)))
- return 0;
+ if (cong) {
+ char cur_cc[TCP_CA_NAME_MAX];
- if (!tcp_cc_eq(cur_cc, cubic_cc))
- return 0;
+ if (bpf_getsockopt(tp, SOL_TCP, TCP_CONGESTION,
+ cur_cc, sizeof(cur_cc)))
+ return 0;
- if (random_retry && bpf_get_prandom_u32() % 4 == 1)
- return 1;
+ if (!tcp_cc_eq(cur_cc, cubic_cc))
+ return 0;
+
+ if (random_retry && bpf_get_prandom_u32() % 4 == 1)
+ return 1;
+
+ bpf_setsockopt(tp, SOL_TCP, TCP_CONGESTION, dctcp_cc, sizeof(dctcp_cc));
+ } else {
+ int val, newval = BPF_SOCK_OPS_ALL_CB_FLAGS;
+ int *sk_storage;
- bpf_setsockopt(tp, SOL_TCP, TCP_CONGESTION, dctcp_cc, sizeof(dctcp_cc));
+ if (bpf_getsockopt(tp, SOL_TCP, TCP_BPF_SOCK_OPS_CB_FLAGS,
+ &val, sizeof(val)))
+ return 0;
+
+ if (val == newval)
+ return 0;
+
+ if (random_retry && bpf_get_prandom_u32() % 4 == 1)
+ return 1;
+
+ if (bpf_setsockopt(tp, SOL_TCP, TCP_BPF_SOCK_OPS_CB_FLAGS,
+ &newval, sizeof(newval)))
+ return 0;
+ /* store flags value for retrieval in cgroup/getsockopt prog */
+ sk_storage = bpf_sk_storage_get(&sk_map, sk, 0,
+ BPF_SK_STORAGE_GET_F_CREATE);
+ if (sk_storage)
+ *sk_storage = newval;
+ }
return 0;
}
Add support to test bpf_setsockopt(.., TCP_BPF_SOCK_OPS_CB_FLAGS, ...) in BPF iterator context; use per-socket storage to store the new value and retrieve it in a cgroup/getsockopt program we attach to allow us to query TCP_BPF_SOCK_OPS_CB_FLAGS via getsockopt. Signed-off-by: Alan Maguire <alan.maguire@oracle.com> --- .../bpf/prog_tests/bpf_iter_setsockopt.c | 83 +++++++++++++------ .../selftests/bpf/progs/bpf_iter_setsockopt.c | 76 ++++++++++++++--- 2 files changed, 123 insertions(+), 36 deletions(-)