485 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2#ifndef __TEST_PROGS_H3#define __TEST_PROGS_H4 5#include <stdio.h>6#include <unistd.h>7#include <errno.h>8#include <string.h>9#include <assert.h>10#include <stdlib.h>11#include <stdarg.h>12#include <time.h>13#include <signal.h>14 15#include <linux/types.h>16typedef __u16 __sum16;17#include <arpa/inet.h>18#include <linux/if_ether.h>19#include <linux/if_packet.h>20#include <linux/ip.h>21#include <linux/ipv6.h>22#include <linux/filter.h>23#include <linux/perf_event.h>24#include <linux/socket.h>25#include <linux/unistd.h>26 27#include <sys/ioctl.h>28#include <sys/wait.h>29#include <sys/types.h>30#include <sys/time.h>31#include <sys/param.h>32#include <fcntl.h>33#include <pthread.h>34#include <linux/bpf.h>35#include <linux/err.h>36#include <bpf/bpf.h>37#include <bpf/libbpf.h>38 39#include "test_iptunnel_common.h"40#include "bpf_util.h"41#include <bpf/bpf_endian.h>42#include "trace_helpers.h"43#include "testing_helpers.h"44 45enum verbosity {46 VERBOSE_NONE,47 VERBOSE_NORMAL,48 VERBOSE_VERY,49 VERBOSE_SUPER,50};51 52struct test_filter {53 char *name;54 char **subtests;55 int subtest_cnt;56};57 58struct test_filter_set {59 struct test_filter *tests;60 int cnt;61};62 63struct test_selector {64 struct test_filter_set whitelist;65 struct test_filter_set blacklist;66 bool *num_set;67 int num_set_len;68};69 70struct subtest_state {71 char *name;72 size_t log_cnt;73 char *log_buf;74 int error_cnt;75 bool skipped;76 bool filtered;77 bool should_tmon;78 79 FILE *stdout_saved;80};81 82struct test_state {83 bool tested;84 bool force_log;85 86 int error_cnt;87 int skip_cnt;88 int sub_succ_cnt;89 90 struct subtest_state *subtest_states;91 int subtest_num;92 93 size_t log_cnt;94 char *log_buf;95 96 FILE *stdout_saved;97};98 99extern int env_verbosity;100 101struct test_env {102 struct test_selector test_selector;103 struct test_selector subtest_selector;104 struct test_selector tmon_selector;105 bool verifier_stats;106 bool debug;107 enum verbosity verbosity;108 109 bool jit_enabled;110 bool has_testmod;111 bool get_test_cnt;112 bool list_test_names;113 114 struct prog_test_def *test; /* current running test */115 struct test_state *test_state; /* current running test state */116 struct subtest_state *subtest_state; /* current running subtest state */117 118 FILE *stdout_saved;119 FILE *stderr_saved;120 int nr_cpus;121 FILE *json;122 123 int succ_cnt; /* successful tests */124 int sub_succ_cnt; /* successful sub-tests */125 int fail_cnt; /* total failed tests + sub-tests */126 int skip_cnt; /* skipped tests */127 128 int saved_netns_fd;129 int workers; /* number of worker process */130 int worker_id; /* id number of current worker, main process is -1 */131 pid_t *worker_pids; /* array of worker pids */132 int *worker_socks; /* array of worker socks */133 int *worker_current_test; /* array of current running test for each worker */134};135 136#define MAX_LOG_TRUNK_SIZE 8192137#define MAX_SUBTEST_NAME 1024138enum msg_type {139 MSG_DO_TEST = 0,140 MSG_TEST_DONE = 1,141 MSG_TEST_LOG = 2,142 MSG_SUBTEST_DONE = 3,143 MSG_EXIT = 255,144};145struct msg {146 enum msg_type type;147 union {148 struct {149 int num;150 } do_test;151 struct {152 int num;153 int sub_succ_cnt;154 int error_cnt;155 int skip_cnt;156 bool have_log;157 int subtest_num;158 } test_done;159 struct {160 char log_buf[MAX_LOG_TRUNK_SIZE + 1];161 bool is_last;162 } test_log;163 struct {164 int num;165 char name[MAX_SUBTEST_NAME + 1];166 int error_cnt;167 bool skipped;168 bool filtered;169 bool have_log;170 } subtest_done;171 };172};173 174extern struct test_env env;175 176void test__force_log(void);177bool test__start_subtest(const char *name);178void test__end_subtest(void);179void test__skip(void);180void test__fail(void);181int test__join_cgroup(const char *path);182 183#define PRINT_FAIL(format...) \184 ({ \185 test__fail(); \186 fprintf(stdout, "%s:FAIL:%d ", __func__, __LINE__); \187 fprintf(stdout, ##format); \188 })189 190#define _CHECK(condition, tag, duration, format...) ({ \191 int __ret = !!(condition); \192 int __save_errno = errno; \193 if (__ret) { \194 test__fail(); \195 fprintf(stdout, "%s:FAIL:%s ", __func__, tag); \196 fprintf(stdout, ##format); \197 } else { \198 fprintf(stdout, "%s:PASS:%s %d nsec\n", \199 __func__, tag, duration); \200 } \201 errno = __save_errno; \202 __ret; \203})204 205#define CHECK_FAIL(condition) ({ \206 int __ret = !!(condition); \207 int __save_errno = errno; \208 if (__ret) { \209 test__fail(); \210 fprintf(stdout, "%s:FAIL:%d\n", __func__, __LINE__); \211 } \212 errno = __save_errno; \213 __ret; \214})215 216#define CHECK(condition, tag, format...) \217 _CHECK(condition, tag, duration, format)218#define CHECK_ATTR(condition, tag, format...) \219 _CHECK(condition, tag, tattr.duration, format)220 221#define ASSERT_FAIL(fmt, args...) ({ \222 static int duration = 0; \223 CHECK(false, "", fmt"\n", ##args); \224 false; \225})226 227#define ASSERT_TRUE(actual, name) ({ \228 static int duration = 0; \229 bool ___ok = (actual); \230 CHECK(!___ok, (name), "unexpected %s: got FALSE\n", (name)); \231 ___ok; \232})233 234#define ASSERT_FALSE(actual, name) ({ \235 static int duration = 0; \236 bool ___ok = !(actual); \237 CHECK(!___ok, (name), "unexpected %s: got TRUE\n", (name)); \238 ___ok; \239})240 241#define ASSERT_EQ(actual, expected, name) ({ \242 static int duration = 0; \243 typeof(actual) ___act = (actual); \244 typeof(expected) ___exp = (expected); \245 bool ___ok = ___act == ___exp; \246 CHECK(!___ok, (name), \247 "unexpected %s: actual %lld != expected %lld\n", \248 (name), (long long)(___act), (long long)(___exp)); \249 ___ok; \250})251 252#define ASSERT_NEQ(actual, expected, name) ({ \253 static int duration = 0; \254 typeof(actual) ___act = (actual); \255 typeof(expected) ___exp = (expected); \256 bool ___ok = ___act != ___exp; \257 CHECK(!___ok, (name), \258 "unexpected %s: actual %lld == expected %lld\n", \259 (name), (long long)(___act), (long long)(___exp)); \260 ___ok; \261})262 263#define ASSERT_LT(actual, expected, name) ({ \264 static int duration = 0; \265 typeof(actual) ___act = (actual); \266 typeof(expected) ___exp = (expected); \267 bool ___ok = ___act < ___exp; \268 CHECK(!___ok, (name), \269 "unexpected %s: actual %lld >= expected %lld\n", \270 (name), (long long)(___act), (long long)(___exp)); \271 ___ok; \272})273 274#define ASSERT_LE(actual, expected, name) ({ \275 static int duration = 0; \276 typeof(actual) ___act = (actual); \277 typeof(expected) ___exp = (expected); \278 bool ___ok = ___act <= ___exp; \279 CHECK(!___ok, (name), \280 "unexpected %s: actual %lld > expected %lld\n", \281 (name), (long long)(___act), (long long)(___exp)); \282 ___ok; \283})284 285#define ASSERT_GT(actual, expected, name) ({ \286 static int duration = 0; \287 typeof(actual) ___act = (actual); \288 typeof(expected) ___exp = (expected); \289 bool ___ok = ___act > ___exp; \290 CHECK(!___ok, (name), \291 "unexpected %s: actual %lld <= expected %lld\n", \292 (name), (long long)(___act), (long long)(___exp)); \293 ___ok; \294})295 296#define ASSERT_GE(actual, expected, name) ({ \297 static int duration = 0; \298 typeof(actual) ___act = (actual); \299 typeof(expected) ___exp = (expected); \300 bool ___ok = ___act >= ___exp; \301 CHECK(!___ok, (name), \302 "unexpected %s: actual %lld < expected %lld\n", \303 (name), (long long)(___act), (long long)(___exp)); \304 ___ok; \305})306 307#define ASSERT_STREQ(actual, expected, name) ({ \308 static int duration = 0; \309 const char *___act = actual; \310 const char *___exp = expected; \311 bool ___ok = strcmp(___act, ___exp) == 0; \312 CHECK(!___ok, (name), \313 "unexpected %s: actual '%s' != expected '%s'\n", \314 (name), ___act, ___exp); \315 ___ok; \316})317 318#define ASSERT_STRNEQ(actual, expected, len, name) ({ \319 static int duration = 0; \320 const char *___act = actual; \321 const char *___exp = expected; \322 int ___len = len; \323 bool ___ok = strncmp(___act, ___exp, ___len) == 0; \324 CHECK(!___ok, (name), \325 "unexpected %s: actual '%.*s' != expected '%.*s'\n", \326 (name), ___len, ___act, ___len, ___exp); \327 ___ok; \328})329 330#define ASSERT_HAS_SUBSTR(str, substr, name) ({ \331 static int duration = 0; \332 const char *___str = str; \333 const char *___substr = substr; \334 bool ___ok = strstr(___str, ___substr) != NULL; \335 CHECK(!___ok, (name), \336 "unexpected %s: '%s' is not a substring of '%s'\n", \337 (name), ___substr, ___str); \338 ___ok; \339})340 341#define ASSERT_OK(res, name) ({ \342 static int duration = 0; \343 long long ___res = (res); \344 bool ___ok = ___res == 0; \345 CHECK(!___ok, (name), "unexpected error: %lld (errno %d)\n", \346 ___res, errno); \347 ___ok; \348})349 350#define ASSERT_ERR(res, name) ({ \351 static int duration = 0; \352 long long ___res = (res); \353 bool ___ok = ___res < 0; \354 CHECK(!___ok, (name), "unexpected success: %lld\n", ___res); \355 ___ok; \356})357 358#define ASSERT_NULL(ptr, name) ({ \359 static int duration = 0; \360 const void *___res = (ptr); \361 bool ___ok = !___res; \362 CHECK(!___ok, (name), "unexpected pointer: %p\n", ___res); \363 ___ok; \364})365 366#define ASSERT_OK_PTR(ptr, name) ({ \367 static int duration = 0; \368 const void *___res = (ptr); \369 int ___err = libbpf_get_error(___res); \370 bool ___ok = ___err == 0; \371 CHECK(!___ok, (name), "unexpected error: %d\n", ___err); \372 ___ok; \373})374 375#define ASSERT_ERR_PTR(ptr, name) ({ \376 static int duration = 0; \377 const void *___res = (ptr); \378 int ___err = libbpf_get_error(___res); \379 bool ___ok = ___err != 0; \380 CHECK(!___ok, (name), "unexpected pointer: %p\n", ___res); \381 ___ok; \382})383 384#define ASSERT_OK_FD(fd, name) ({ \385 static int duration = 0; \386 int ___fd = (fd); \387 bool ___ok = ___fd >= 0; \388 CHECK(!___ok, (name), "unexpected fd: %d (errno %d)\n", \389 ___fd, errno); \390 ___ok; \391})392 393#define SYS(goto_label, fmt, ...) \394 ({ \395 char cmd[1024]; \396 snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__); \397 if (!ASSERT_OK(system(cmd), cmd)) \398 goto goto_label; \399 })400 401#define ALL_TO_DEV_NULL " >/dev/null 2>&1"402 403#define SYS_NOFAIL(fmt, ...) \404 ({ \405 char cmd[1024]; \406 int n; \407 n = snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__); \408 if (n < sizeof(cmd) && sizeof(cmd) - n >= sizeof(ALL_TO_DEV_NULL)) \409 strcat(cmd, ALL_TO_DEV_NULL); \410 system(cmd); \411 })412 413int start_libbpf_log_capture(void);414char *stop_libbpf_log_capture(void);415 416static inline __u64 ptr_to_u64(const void *ptr)417{418 return (__u64) (unsigned long) ptr;419}420 421static inline void *u64_to_ptr(__u64 ptr)422{423 return (void *) (unsigned long) ptr;424}425 426int bpf_find_map(const char *test, struct bpf_object *obj, const char *name);427int compare_map_keys(int map1_fd, int map2_fd);428int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len);429int trigger_module_test_read(int read_sz);430int trigger_module_test_write(int write_sz);431int write_sysctl(const char *sysctl, const char *value);432int get_bpf_max_tramp_links_from(struct btf *btf);433int get_bpf_max_tramp_links(void);434 435struct netns_obj;436struct netns_obj *netns_new(const char *name, bool open);437void netns_free(struct netns_obj *netns);438 439#ifdef __x86_64__440#define SYS_NANOSLEEP_KPROBE_NAME "__x64_sys_nanosleep"441#elif defined(__s390x__)442#define SYS_NANOSLEEP_KPROBE_NAME "__s390x_sys_nanosleep"443#elif defined(__aarch64__)444#define SYS_NANOSLEEP_KPROBE_NAME "__arm64_sys_nanosleep"445#elif defined(__riscv)446#define SYS_NANOSLEEP_KPROBE_NAME "__riscv_sys_nanosleep"447#else448#define SYS_NANOSLEEP_KPROBE_NAME "sys_nanosleep"449#endif450 451#define BPF_TESTMOD_TEST_FILE "/sys/kernel/bpf_testmod"452 453typedef int (*pre_execution_cb)(struct bpf_object *obj);454 455struct test_loader {456 char *log_buf;457 size_t log_buf_sz;458 pre_execution_cb pre_execution_cb;459 460 struct bpf_object *obj;461};462 463static inline void test_loader__set_pre_execution_cb(struct test_loader *tester,464 pre_execution_cb cb)465{466 tester->pre_execution_cb = cb;467}468 469typedef const void *(*skel_elf_bytes_fn)(size_t *sz);470 471extern void test_loader__run_subtests(struct test_loader *tester,472 const char *skel_name,473 skel_elf_bytes_fn elf_bytes_factory);474 475extern void test_loader_fini(struct test_loader *tester);476 477#define RUN_TESTS(skel) ({ \478 struct test_loader tester = {}; \479 \480 test_loader__run_subtests(&tester, #skel, skel##__elf_bytes); \481 test_loader_fini(&tester); \482})483 484#endif /* __TEST_PROGS_H */485