From: Stanislav Fomichev Date: Wed, 4 Sep 2019 16:25:08 +0000 (-0700) Subject: selftests/bpf: test_progs: convert test_sockopt_inherit X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=e3e02e1d9c24b0c3a36f9c854ae80e61fd62b2a9;p=linux.git selftests/bpf: test_progs: convert test_sockopt_inherit Move the files, adjust includes, remove entry from Makefile & .gitignore I also added pthread_cond_wait for the server thread startup. We don't want to connect to the server that's not yet up (for some reason this existing race is now more prominent with test_progs). Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore index 4143add5a11e9..5b06bb45b5006 100644 --- a/tools/testing/selftests/bpf/.gitignore +++ b/tools/testing/selftests/bpf/.gitignore @@ -39,5 +39,4 @@ libbpf.so.* test_hashmap test_btf_dump xdping -test_sockopt_inherit test_tcp_rtt diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 0ab9642c4f5e5..4d9a0304a0110 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -28,8 +28,7 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test test_sock test_btf test_sockmap get_cgroup_id_user test_socket_cookie \ test_cgroup_storage test_select_reuseport test_section_names \ test_netcnt test_tcpnotify_user test_sock_fields test_sysctl test_hashmap \ - test_btf_dump test_cgroup_attach xdping \ - test_sockopt_inherit test_tcp_rtt + test_btf_dump test_cgroup_attach xdping test_tcp_rtt BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c))) TEST_GEN_FILES = $(BPF_OBJ_FILES) @@ -113,7 +112,6 @@ $(OUTPUT)/test_netcnt: cgroup_helpers.c $(OUTPUT)/test_sock_fields: cgroup_helpers.c $(OUTPUT)/test_sysctl: cgroup_helpers.c $(OUTPUT)/test_cgroup_attach: cgroup_helpers.c -$(OUTPUT)/test_sockopt_inherit: cgroup_helpers.c $(OUTPUT)/test_tcp_rtt: cgroup_helpers.c .PHONY: force diff --git a/tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c b/tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c new file mode 100644 index 0000000000000..6cbeea7b4bf16 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include "cgroup_helpers.h" + +#define SOL_CUSTOM 0xdeadbeef +#define CUSTOM_INHERIT1 0 +#define CUSTOM_INHERIT2 1 +#define CUSTOM_LISTENER 2 + +static int connect_to_server(int server_fd) +{ + struct sockaddr_storage addr; + socklen_t len = sizeof(addr); + int fd; + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) { + log_err("Failed to create client socket"); + return -1; + } + + if (getsockname(server_fd, (struct sockaddr *)&addr, &len)) { + log_err("Failed to get server addr"); + goto out; + } + + if (connect(fd, (const struct sockaddr *)&addr, len) < 0) { + log_err("Fail to connect to server"); + goto out; + } + + return fd; + +out: + close(fd); + return -1; +} + +static int verify_sockopt(int fd, int optname, const char *msg, char expected) +{ + socklen_t optlen = 1; + char buf = 0; + int err; + + err = getsockopt(fd, SOL_CUSTOM, optname, &buf, &optlen); + if (err) { + log_err("%s: failed to call getsockopt", msg); + return 1; + } + + printf("%s %d: got=0x%x ? expected=0x%x\n", msg, optname, buf, expected); + + if (buf != expected) { + log_err("%s: unexpected getsockopt value %d != %d", msg, + buf, expected); + return 1; + } + + return 0; +} + +static pthread_mutex_t server_started_mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t server_started = PTHREAD_COND_INITIALIZER; + +static void *server_thread(void *arg) +{ + struct sockaddr_storage addr; + socklen_t len = sizeof(addr); + int fd = *(int *)arg; + int client_fd; + int err = 0; + + err = listen(fd, 1); + + pthread_mutex_lock(&server_started_mtx); + pthread_cond_signal(&server_started); + pthread_mutex_unlock(&server_started_mtx); + + if (CHECK_FAIL(err < 0)) { + perror("Failed to listed on socket"); + return NULL; + } + + err += verify_sockopt(fd, CUSTOM_INHERIT1, "listen", 1); + err += verify_sockopt(fd, CUSTOM_INHERIT2, "listen", 1); + err += verify_sockopt(fd, CUSTOM_LISTENER, "listen", 1); + + client_fd = accept(fd, (struct sockaddr *)&addr, &len); + if (CHECK_FAIL(client_fd < 0)) { + perror("Failed to accept client"); + return NULL; + } + + err += verify_sockopt(client_fd, CUSTOM_INHERIT1, "accept", 1); + err += verify_sockopt(client_fd, CUSTOM_INHERIT2, "accept", 1); + err += verify_sockopt(client_fd, CUSTOM_LISTENER, "accept", 0); + + close(client_fd); + + return (void *)(long)err; +} + +static int start_server(void) +{ + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl(INADDR_LOOPBACK), + }; + char buf; + int err; + int fd; + int i; + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) { + log_err("Failed to create server socket"); + return -1; + } + + for (i = CUSTOM_INHERIT1; i <= CUSTOM_LISTENER; i++) { + buf = 0x01; + err = setsockopt(fd, SOL_CUSTOM, i, &buf, 1); + if (err) { + log_err("Failed to call setsockopt(%d)", i); + close(fd); + return -1; + } + } + + if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) { + log_err("Failed to bind socket"); + close(fd); + return -1; + } + + return fd; +} + +static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title) +{ + enum bpf_attach_type attach_type; + enum bpf_prog_type prog_type; + struct bpf_program *prog; + int err; + + err = libbpf_prog_type_by_name(title, &prog_type, &attach_type); + if (err) { + log_err("Failed to deduct types for %s BPF program", title); + return -1; + } + + prog = bpf_object__find_program_by_title(obj, title); + if (!prog) { + log_err("Failed to find %s BPF program", title); + return -1; + } + + err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, + attach_type, 0); + if (err) { + log_err("Failed to attach %s BPF program", title); + return -1; + } + + return 0; +} + +static void run_test(int cgroup_fd) +{ + struct bpf_prog_load_attr attr = { + .file = "./sockopt_inherit.o", + }; + int server_fd = -1, client_fd; + struct bpf_object *obj; + void *server_err; + pthread_t tid; + int ignored; + int err; + + err = bpf_prog_load_xattr(&attr, &obj, &ignored); + if (CHECK_FAIL(err)) + return; + + err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt"); + if (CHECK_FAIL(err)) + goto close_bpf_object; + + err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt"); + if (CHECK_FAIL(err)) + goto close_bpf_object; + + server_fd = start_server(); + if (CHECK_FAIL(server_fd < 0)) + goto close_bpf_object; + + if (CHECK_FAIL(pthread_create(&tid, NULL, server_thread, + (void *)&server_fd))) + goto close_bpf_object; + + pthread_mutex_lock(&server_started_mtx); + pthread_cond_wait(&server_started, &server_started_mtx); + pthread_mutex_unlock(&server_started_mtx); + + client_fd = connect_to_server(server_fd); + if (CHECK_FAIL(client_fd < 0)) + goto close_server_fd; + + CHECK_FAIL(verify_sockopt(client_fd, CUSTOM_INHERIT1, "connect", 0)); + CHECK_FAIL(verify_sockopt(client_fd, CUSTOM_INHERIT2, "connect", 0)); + CHECK_FAIL(verify_sockopt(client_fd, CUSTOM_LISTENER, "connect", 0)); + + pthread_join(tid, &server_err); + + err = (int)(long)server_err; + CHECK_FAIL(err); + + close(client_fd); + +close_server_fd: + close(server_fd); +close_bpf_object: + bpf_object__close(obj); +} + +void test_sockopt_inherit(void) +{ + int cgroup_fd; + + cgroup_fd = test__join_cgroup("/sockopt_inherit"); + if (CHECK_FAIL(cgroup_fd < 0)) + return; + + run_test(cgroup_fd); + close(cgroup_fd); +} diff --git a/tools/testing/selftests/bpf/test_sockopt_inherit.c b/tools/testing/selftests/bpf/test_sockopt_inherit.c deleted file mode 100644 index 1bf699815b9b7..0000000000000 --- a/tools/testing/selftests/bpf/test_sockopt_inherit.c +++ /dev/null @@ -1,253 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "bpf_rlimit.h" -#include "bpf_util.h" -#include "cgroup_helpers.h" - -#define CG_PATH "/sockopt_inherit" -#define SOL_CUSTOM 0xdeadbeef -#define CUSTOM_INHERIT1 0 -#define CUSTOM_INHERIT2 1 -#define CUSTOM_LISTENER 2 - -static int connect_to_server(int server_fd) -{ - struct sockaddr_storage addr; - socklen_t len = sizeof(addr); - int fd; - - fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) { - log_err("Failed to create client socket"); - return -1; - } - - if (getsockname(server_fd, (struct sockaddr *)&addr, &len)) { - log_err("Failed to get server addr"); - goto out; - } - - if (connect(fd, (const struct sockaddr *)&addr, len) < 0) { - log_err("Fail to connect to server"); - goto out; - } - - return fd; - -out: - close(fd); - return -1; -} - -static int verify_sockopt(int fd, int optname, const char *msg, char expected) -{ - socklen_t optlen = 1; - char buf = 0; - int err; - - err = getsockopt(fd, SOL_CUSTOM, optname, &buf, &optlen); - if (err) { - log_err("%s: failed to call getsockopt", msg); - return 1; - } - - printf("%s %d: got=0x%x ? expected=0x%x\n", msg, optname, buf, expected); - - if (buf != expected) { - log_err("%s: unexpected getsockopt value %d != %d", msg, - buf, expected); - return 1; - } - - return 0; -} - -static void *server_thread(void *arg) -{ - struct sockaddr_storage addr; - socklen_t len = sizeof(addr); - int fd = *(int *)arg; - int client_fd; - int err = 0; - - if (listen(fd, 1) < 0) - error(1, errno, "Failed to listed on socket"); - - err += verify_sockopt(fd, CUSTOM_INHERIT1, "listen", 1); - err += verify_sockopt(fd, CUSTOM_INHERIT2, "listen", 1); - err += verify_sockopt(fd, CUSTOM_LISTENER, "listen", 1); - - client_fd = accept(fd, (struct sockaddr *)&addr, &len); - if (client_fd < 0) - error(1, errno, "Failed to accept client"); - - err += verify_sockopt(client_fd, CUSTOM_INHERIT1, "accept", 1); - err += verify_sockopt(client_fd, CUSTOM_INHERIT2, "accept", 1); - err += verify_sockopt(client_fd, CUSTOM_LISTENER, "accept", 0); - - close(client_fd); - - return (void *)(long)err; -} - -static int start_server(void) -{ - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_addr.s_addr = htonl(INADDR_LOOPBACK), - }; - char buf; - int err; - int fd; - int i; - - fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) { - log_err("Failed to create server socket"); - return -1; - } - - for (i = CUSTOM_INHERIT1; i <= CUSTOM_LISTENER; i++) { - buf = 0x01; - err = setsockopt(fd, SOL_CUSTOM, i, &buf, 1); - if (err) { - log_err("Failed to call setsockopt(%d)", i); - close(fd); - return -1; - } - } - - if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) { - log_err("Failed to bind socket"); - close(fd); - return -1; - } - - return fd; -} - -static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title) -{ - enum bpf_attach_type attach_type; - enum bpf_prog_type prog_type; - struct bpf_program *prog; - int err; - - err = libbpf_prog_type_by_name(title, &prog_type, &attach_type); - if (err) { - log_err("Failed to deduct types for %s BPF program", title); - return -1; - } - - prog = bpf_object__find_program_by_title(obj, title); - if (!prog) { - log_err("Failed to find %s BPF program", title); - return -1; - } - - err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, - attach_type, 0); - if (err) { - log_err("Failed to attach %s BPF program", title); - return -1; - } - - return 0; -} - -static int run_test(int cgroup_fd) -{ - struct bpf_prog_load_attr attr = { - .file = "./sockopt_inherit.o", - }; - int server_fd = -1, client_fd; - struct bpf_object *obj; - void *server_err; - pthread_t tid; - int ignored; - int err; - - err = bpf_prog_load_xattr(&attr, &obj, &ignored); - if (err) { - log_err("Failed to load BPF object"); - return -1; - } - - err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt"); - if (err) - goto close_bpf_object; - - err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt"); - if (err) - goto close_bpf_object; - - server_fd = start_server(); - if (server_fd < 0) { - err = -1; - goto close_bpf_object; - } - - pthread_create(&tid, NULL, server_thread, (void *)&server_fd); - - client_fd = connect_to_server(server_fd); - if (client_fd < 0) { - err = -1; - goto close_server_fd; - } - - err += verify_sockopt(client_fd, CUSTOM_INHERIT1, "connect", 0); - err += verify_sockopt(client_fd, CUSTOM_INHERIT2, "connect", 0); - err += verify_sockopt(client_fd, CUSTOM_LISTENER, "connect", 0); - - pthread_join(tid, &server_err); - - err += (int)(long)server_err; - - close(client_fd); - -close_server_fd: - close(server_fd); -close_bpf_object: - bpf_object__close(obj); - return err; -} - -int main(int args, char **argv) -{ - int cgroup_fd; - int err = EXIT_SUCCESS; - - if (setup_cgroup_environment()) - return err; - - cgroup_fd = create_and_get_cgroup(CG_PATH); - if (cgroup_fd < 0) - goto cleanup_cgroup_env; - - if (join_cgroup(CG_PATH)) - goto cleanup_cgroup; - - if (run_test(cgroup_fd)) - err = EXIT_FAILURE; - - printf("test_sockopt_inherit: %s\n", - err == EXIT_SUCCESS ? "PASSED" : "FAILED"); - -cleanup_cgroup: - close(cgroup_fd); -cleanup_cgroup_env: - cleanup_cgroup_environment(); - return err; -}