mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-09 07:14:48 +08:00
4939b2847d
Nearly every user of cgroup helpers does the same sequence of API calls. So push these into a single helper cgroup_setup_and_join. The cases that do a bit of extra logic are test_progs which currently uses an env variable to decide if it needs to setup the cgroup environment or can use an existingi environment. And then tests that are doing cgroup tests themselves. We skip these cases for now. Signed-off-by: John Fastabend <john.fastabend@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Andrii Nakryiko <andriin@fb.com> Link: https://lore.kernel.org/bpf/159623335418.30208.15807461815525100199.stgit@john-XPS-13-9370
166 lines
3.9 KiB
C
166 lines
3.9 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <linux/bpf.h>
|
|
#include <sys/types.h>
|
|
#include <bpf/bpf.h>
|
|
#include <bpf/libbpf.h>
|
|
|
|
#include "bpf_rlimit.h"
|
|
#include "bpf_util.h"
|
|
#include "cgroup_helpers.h"
|
|
|
|
#include "test_tcpbpf.h"
|
|
|
|
/* 3 comes from one listening socket + both ends of the connection */
|
|
#define EXPECTED_CLOSE_EVENTS 3
|
|
|
|
#define EXPECT_EQ(expected, actual, fmt) \
|
|
do { \
|
|
if ((expected) != (actual)) { \
|
|
printf(" Value of: " #actual "\n" \
|
|
" Actual: %" fmt "\n" \
|
|
" Expected: %" fmt "\n", \
|
|
(actual), (expected)); \
|
|
ret--; \
|
|
} \
|
|
} while (0)
|
|
|
|
int verify_result(const struct tcpbpf_globals *result)
|
|
{
|
|
__u32 expected_events;
|
|
int ret = 0;
|
|
|
|
expected_events = ((1 << BPF_SOCK_OPS_TIMEOUT_INIT) |
|
|
(1 << BPF_SOCK_OPS_RWND_INIT) |
|
|
(1 << BPF_SOCK_OPS_TCP_CONNECT_CB) |
|
|
(1 << BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) |
|
|
(1 << BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB) |
|
|
(1 << BPF_SOCK_OPS_NEEDS_ECN) |
|
|
(1 << BPF_SOCK_OPS_STATE_CB) |
|
|
(1 << BPF_SOCK_OPS_TCP_LISTEN_CB));
|
|
|
|
EXPECT_EQ(expected_events, result->event_map, "#" PRIx32);
|
|
EXPECT_EQ(501ULL, result->bytes_received, "llu");
|
|
EXPECT_EQ(1002ULL, result->bytes_acked, "llu");
|
|
EXPECT_EQ(1, result->data_segs_in, PRIu32);
|
|
EXPECT_EQ(1, result->data_segs_out, PRIu32);
|
|
EXPECT_EQ(0x80, result->bad_cb_test_rv, PRIu32);
|
|
EXPECT_EQ(0, result->good_cb_test_rv, PRIu32);
|
|
EXPECT_EQ(1, result->num_listen, PRIu32);
|
|
EXPECT_EQ(EXPECTED_CLOSE_EVENTS, result->num_close_events, PRIu32);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int verify_sockopt_result(int sock_map_fd)
|
|
{
|
|
__u32 key = 0;
|
|
int ret = 0;
|
|
int res;
|
|
int rv;
|
|
|
|
/* check setsockopt for SAVE_SYN */
|
|
rv = bpf_map_lookup_elem(sock_map_fd, &key, &res);
|
|
EXPECT_EQ(0, rv, "d");
|
|
EXPECT_EQ(0, res, "d");
|
|
key = 1;
|
|
/* check getsockopt for SAVED_SYN */
|
|
rv = bpf_map_lookup_elem(sock_map_fd, &key, &res);
|
|
EXPECT_EQ(0, rv, "d");
|
|
EXPECT_EQ(1, res, "d");
|
|
return ret;
|
|
}
|
|
|
|
static int bpf_find_map(const char *test, struct bpf_object *obj,
|
|
const char *name)
|
|
{
|
|
struct bpf_map *map;
|
|
|
|
map = bpf_object__find_map_by_name(obj, name);
|
|
if (!map) {
|
|
printf("%s:FAIL:map '%s' not found\n", test, name);
|
|
return -1;
|
|
}
|
|
return bpf_map__fd(map);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
const char *file = "test_tcpbpf_kern.o";
|
|
int prog_fd, map_fd, sock_map_fd;
|
|
struct tcpbpf_globals g = {0};
|
|
const char *cg_path = "/foo";
|
|
int error = EXIT_FAILURE;
|
|
struct bpf_object *obj;
|
|
int cg_fd = -1;
|
|
int retry = 10;
|
|
__u32 key = 0;
|
|
int rv;
|
|
|
|
cg_fd = cgroup_setup_and_join(cg_path);
|
|
if (cg_fd < 0)
|
|
goto err;
|
|
|
|
if (bpf_prog_load(file, BPF_PROG_TYPE_SOCK_OPS, &obj, &prog_fd)) {
|
|
printf("FAILED: load_bpf_file failed for: %s\n", file);
|
|
goto err;
|
|
}
|
|
|
|
rv = bpf_prog_attach(prog_fd, cg_fd, BPF_CGROUP_SOCK_OPS, 0);
|
|
if (rv) {
|
|
printf("FAILED: bpf_prog_attach: %d (%s)\n",
|
|
error, strerror(errno));
|
|
goto err;
|
|
}
|
|
|
|
if (system("./tcp_server.py")) {
|
|
printf("FAILED: TCP server\n");
|
|
goto err;
|
|
}
|
|
|
|
map_fd = bpf_find_map(__func__, obj, "global_map");
|
|
if (map_fd < 0)
|
|
goto err;
|
|
|
|
sock_map_fd = bpf_find_map(__func__, obj, "sockopt_results");
|
|
if (sock_map_fd < 0)
|
|
goto err;
|
|
|
|
retry_lookup:
|
|
rv = bpf_map_lookup_elem(map_fd, &key, &g);
|
|
if (rv != 0) {
|
|
printf("FAILED: bpf_map_lookup_elem returns %d\n", rv);
|
|
goto err;
|
|
}
|
|
|
|
if (g.num_close_events != EXPECTED_CLOSE_EVENTS && retry--) {
|
|
printf("Unexpected number of close events (%d), retrying!\n",
|
|
g.num_close_events);
|
|
usleep(100);
|
|
goto retry_lookup;
|
|
}
|
|
|
|
if (verify_result(&g)) {
|
|
printf("FAILED: Wrong stats\n");
|
|
goto err;
|
|
}
|
|
|
|
if (verify_sockopt_result(sock_map_fd)) {
|
|
printf("FAILED: Wrong sockopt stats\n");
|
|
goto err;
|
|
}
|
|
|
|
printf("PASSED!\n");
|
|
error = 0;
|
|
err:
|
|
bpf_prog_detach(cg_fd, BPF_CGROUP_SOCK_OPS);
|
|
close(cg_fd);
|
|
cleanup_cgroup_environment();
|
|
return error;
|
|
}
|