1 // SPDX-License-Identifier: GPL-2.0
11 #include <bpf/libbpf.h>
13 #include "bpf_rlimit.h"
15 #include "cgroup_helpers.h"
17 #include "test_tcpbpf.h"
19 /* 3 comes from one listening socket + both ends of the connection */
20 #define EXPECTED_CLOSE_EVENTS 3
22 #define EXPECT_EQ(expected, actual, fmt) \
24 if ((expected) != (actual)) { \
25 printf(" Value of: " #actual "\n" \
26 " Actual: %" fmt "\n" \
27 " Expected: %" fmt "\n", \
28 (actual), (expected)); \
33 int verify_result(const struct tcpbpf_globals
*result
)
35 __u32 expected_events
;
38 expected_events
= ((1 << BPF_SOCK_OPS_TIMEOUT_INIT
) |
39 (1 << BPF_SOCK_OPS_RWND_INIT
) |
40 (1 << BPF_SOCK_OPS_TCP_CONNECT_CB
) |
41 (1 << BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB
) |
42 (1 << BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB
) |
43 (1 << BPF_SOCK_OPS_NEEDS_ECN
) |
44 (1 << BPF_SOCK_OPS_STATE_CB
) |
45 (1 << BPF_SOCK_OPS_TCP_LISTEN_CB
));
47 EXPECT_EQ(expected_events
, result
->event_map
, "#" PRIx32
);
48 EXPECT_EQ(501ULL, result
->bytes_received
, "llu");
49 EXPECT_EQ(1002ULL, result
->bytes_acked
, "llu");
50 EXPECT_EQ(1, result
->data_segs_in
, PRIu32
);
51 EXPECT_EQ(1, result
->data_segs_out
, PRIu32
);
52 EXPECT_EQ(0x80, result
->bad_cb_test_rv
, PRIu32
);
53 EXPECT_EQ(0, result
->good_cb_test_rv
, PRIu32
);
54 EXPECT_EQ(1, result
->num_listen
, PRIu32
);
55 EXPECT_EQ(EXPECTED_CLOSE_EVENTS
, result
->num_close_events
, PRIu32
);
60 int verify_sockopt_result(int sock_map_fd
)
67 /* check setsockopt for SAVE_SYN */
68 rv
= bpf_map_lookup_elem(sock_map_fd
, &key
, &res
);
69 EXPECT_EQ(0, rv
, "d");
70 EXPECT_EQ(0, res
, "d");
72 /* check getsockopt for SAVED_SYN */
73 rv
= bpf_map_lookup_elem(sock_map_fd
, &key
, &res
);
74 EXPECT_EQ(0, rv
, "d");
75 EXPECT_EQ(1, res
, "d");
79 static int bpf_find_map(const char *test
, struct bpf_object
*obj
,
84 map
= bpf_object__find_map_by_name(obj
, name
);
86 printf("%s:FAIL:map '%s' not found\n", test
, name
);
89 return bpf_map__fd(map
);
92 int main(int argc
, char **argv
)
94 const char *file
= "test_tcpbpf_kern.o";
95 int prog_fd
, map_fd
, sock_map_fd
;
96 struct tcpbpf_globals g
= {0};
97 const char *cg_path
= "/foo";
98 int error
= EXIT_FAILURE
;
99 struct bpf_object
*obj
;
105 if (setup_cgroup_environment())
108 cg_fd
= create_and_get_cgroup(cg_path
);
112 if (join_cgroup(cg_path
))
115 if (bpf_prog_load(file
, BPF_PROG_TYPE_SOCK_OPS
, &obj
, &prog_fd
)) {
116 printf("FAILED: load_bpf_file failed for: %s\n", file
);
120 rv
= bpf_prog_attach(prog_fd
, cg_fd
, BPF_CGROUP_SOCK_OPS
, 0);
122 printf("FAILED: bpf_prog_attach: %d (%s)\n",
123 error
, strerror(errno
));
127 if (system("./tcp_server.py")) {
128 printf("FAILED: TCP server\n");
132 map_fd
= bpf_find_map(__func__
, obj
, "global_map");
136 sock_map_fd
= bpf_find_map(__func__
, obj
, "sockopt_results");
141 rv
= bpf_map_lookup_elem(map_fd
, &key
, &g
);
143 printf("FAILED: bpf_map_lookup_elem returns %d\n", rv
);
147 if (g
.num_close_events
!= EXPECTED_CLOSE_EVENTS
&& retry
--) {
148 printf("Unexpected number of close events (%d), retrying!\n",
154 if (verify_result(&g
)) {
155 printf("FAILED: Wrong stats\n");
159 if (verify_sockopt_result(sock_map_fd
)) {
160 printf("FAILED: Wrong sockopt stats\n");
167 bpf_prog_detach(cg_fd
, BPF_CGROUP_SOCK_OPS
);
169 cleanup_cgroup_environment();