testing_helpers.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
  2. /* Copyright (C) 2019 Netronome Systems, Inc. */
  3. /* Copyright (C) 2020 Facebook, Inc. */
  4. #include <ctype.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <bpf/bpf.h>
  9. #include <bpf/libbpf.h>
  10. #include "disasm.h"
  11. #include "test_progs.h"
  12. #include "testing_helpers.h"
  13. #include <linux/membarrier.h>
  14. int parse_num_list(const char *s, bool **num_set, int *num_set_len)
  15. {
  16. int i, set_len = 0, new_len, num, start = 0, end = -1;
  17. bool *set = NULL, *tmp, parsing_end = false;
  18. char *next;
  19. while (s[0]) {
  20. errno = 0;
  21. num = strtol(s, &next, 10);
  22. if (errno)
  23. return -errno;
  24. if (parsing_end)
  25. end = num;
  26. else
  27. start = num;
  28. if (!parsing_end && *next == '-') {
  29. s = next + 1;
  30. parsing_end = true;
  31. continue;
  32. } else if (*next == ',') {
  33. parsing_end = false;
  34. s = next + 1;
  35. end = num;
  36. } else if (*next == '\0') {
  37. parsing_end = false;
  38. s = next;
  39. end = num;
  40. } else {
  41. return -EINVAL;
  42. }
  43. if (start > end)
  44. return -EINVAL;
  45. if (end + 1 > set_len) {
  46. new_len = end + 1;
  47. tmp = realloc(set, new_len);
  48. if (!tmp) {
  49. free(set);
  50. return -ENOMEM;
  51. }
  52. for (i = set_len; i < start; i++)
  53. tmp[i] = false;
  54. set = tmp;
  55. set_len = new_len;
  56. }
  57. for (i = start; i <= end; i++)
  58. set[i] = true;
  59. }
  60. if (!set || parsing_end)
  61. return -EINVAL;
  62. *num_set = set;
  63. *num_set_len = set_len;
  64. return 0;
  65. }
  66. static int do_insert_test(struct test_filter_set *set,
  67. char *test_str,
  68. char *subtest_str)
  69. {
  70. struct test_filter *tmp, *test;
  71. char **ctmp;
  72. int i;
  73. for (i = 0; i < set->cnt; i++) {
  74. test = &set->tests[i];
  75. if (strcmp(test_str, test->name) == 0) {
  76. free(test_str);
  77. goto subtest;
  78. }
  79. }
  80. tmp = realloc(set->tests, sizeof(*test) * (set->cnt + 1));
  81. if (!tmp)
  82. return -ENOMEM;
  83. set->tests = tmp;
  84. test = &set->tests[set->cnt];
  85. test->name = test_str;
  86. test->subtests = NULL;
  87. test->subtest_cnt = 0;
  88. set->cnt++;
  89. subtest:
  90. if (!subtest_str)
  91. return 0;
  92. for (i = 0; i < test->subtest_cnt; i++) {
  93. if (strcmp(subtest_str, test->subtests[i]) == 0) {
  94. free(subtest_str);
  95. return 0;
  96. }
  97. }
  98. ctmp = realloc(test->subtests,
  99. sizeof(*test->subtests) * (test->subtest_cnt + 1));
  100. if (!ctmp)
  101. return -ENOMEM;
  102. test->subtests = ctmp;
  103. test->subtests[test->subtest_cnt] = subtest_str;
  104. test->subtest_cnt++;
  105. return 0;
  106. }
  107. static int insert_test(struct test_filter_set *set,
  108. char *test_spec,
  109. bool is_glob_pattern)
  110. {
  111. char *pattern, *subtest_str, *ext_test_str, *ext_subtest_str = NULL;
  112. int glob_chars = 0;
  113. if (is_glob_pattern) {
  114. pattern = "%s";
  115. } else {
  116. pattern = "*%s*";
  117. glob_chars = 2;
  118. }
  119. subtest_str = strchr(test_spec, '/');
  120. if (subtest_str) {
  121. *subtest_str = '\0';
  122. subtest_str += 1;
  123. }
  124. ext_test_str = malloc(strlen(test_spec) + glob_chars + 1);
  125. if (!ext_test_str)
  126. goto err;
  127. sprintf(ext_test_str, pattern, test_spec);
  128. if (subtest_str) {
  129. ext_subtest_str = malloc(strlen(subtest_str) + glob_chars + 1);
  130. if (!ext_subtest_str)
  131. goto err;
  132. sprintf(ext_subtest_str, pattern, subtest_str);
  133. }
  134. return do_insert_test(set, ext_test_str, ext_subtest_str);
  135. err:
  136. free(ext_test_str);
  137. free(ext_subtest_str);
  138. return -ENOMEM;
  139. }
  140. int parse_test_list_file(const char *path,
  141. struct test_filter_set *set,
  142. bool is_glob_pattern)
  143. {
  144. char *buf = NULL, *capture_start, *capture_end, *scan_end;
  145. size_t buflen = 0;
  146. int err = 0;
  147. FILE *f;
  148. f = fopen(path, "r");
  149. if (!f) {
  150. err = -errno;
  151. fprintf(stderr, "Failed to open '%s': %d\n", path, err);
  152. return err;
  153. }
  154. while (getline(&buf, &buflen, f) != -1) {
  155. capture_start = buf;
  156. while (isspace(*capture_start))
  157. ++capture_start;
  158. capture_end = capture_start;
  159. scan_end = capture_start;
  160. while (*scan_end && *scan_end != '#') {
  161. if (!isspace(*scan_end))
  162. capture_end = scan_end;
  163. ++scan_end;
  164. }
  165. if (capture_end == capture_start)
  166. continue;
  167. *(++capture_end) = '\0';
  168. err = insert_test(set, capture_start, is_glob_pattern);
  169. if (err)
  170. break;
  171. }
  172. fclose(f);
  173. return err;
  174. }
  175. int parse_test_list(const char *s,
  176. struct test_filter_set *set,
  177. bool is_glob_pattern)
  178. {
  179. char *input, *state = NULL, *test_spec;
  180. int err = 0, cnt = 0;
  181. input = strdup(s);
  182. if (!input)
  183. return -ENOMEM;
  184. while ((test_spec = strtok_r(cnt++ ? NULL : input, ",", &state))) {
  185. err = insert_test(set, test_spec, is_glob_pattern);
  186. if (err)
  187. break;
  188. }
  189. free(input);
  190. return err;
  191. }
  192. __u32 link_info_prog_id(const struct bpf_link *link, struct bpf_link_info *info)
  193. {
  194. __u32 info_len = sizeof(*info);
  195. int err;
  196. memset(info, 0, sizeof(*info));
  197. err = bpf_link_get_info_by_fd(bpf_link__fd(link), info, &info_len);
  198. if (err) {
  199. printf("failed to get link info: %d\n", -errno);
  200. return 0;
  201. }
  202. return info->prog_id;
  203. }
  204. int extra_prog_load_log_flags = 0;
  205. int testing_prog_flags(void)
  206. {
  207. static int cached_flags = -1;
  208. static int prog_flags[] = { BPF_F_TEST_RND_HI32, BPF_F_TEST_REG_INVARIANTS };
  209. static struct bpf_insn insns[] = {
  210. BPF_MOV64_IMM(BPF_REG_0, 0),
  211. BPF_EXIT_INSN(),
  212. };
  213. int insn_cnt = ARRAY_SIZE(insns), i, fd, flags = 0;
  214. LIBBPF_OPTS(bpf_prog_load_opts, opts);
  215. if (cached_flags >= 0)
  216. return cached_flags;
  217. for (i = 0; i < ARRAY_SIZE(prog_flags); i++) {
  218. opts.prog_flags = prog_flags[i];
  219. fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, "flag-test", "GPL",
  220. insns, insn_cnt, &opts);
  221. if (fd >= 0) {
  222. flags |= prog_flags[i];
  223. close(fd);
  224. }
  225. }
  226. cached_flags = flags;
  227. return cached_flags;
  228. }
  229. int bpf_prog_test_load(const char *file, enum bpf_prog_type type,
  230. struct bpf_object **pobj, int *prog_fd)
  231. {
  232. LIBBPF_OPTS(bpf_object_open_opts, opts,
  233. .kernel_log_level = extra_prog_load_log_flags,
  234. );
  235. struct bpf_object *obj;
  236. struct bpf_program *prog;
  237. __u32 flags;
  238. int err;
  239. obj = bpf_object__open_file(file, &opts);
  240. if (!obj)
  241. return -errno;
  242. prog = bpf_object__next_program(obj, NULL);
  243. if (!prog) {
  244. err = -ENOENT;
  245. goto err_out;
  246. }
  247. if (type != BPF_PROG_TYPE_UNSPEC && bpf_program__type(prog) != type)
  248. bpf_program__set_type(prog, type);
  249. flags = bpf_program__flags(prog) | testing_prog_flags();
  250. bpf_program__set_flags(prog, flags);
  251. err = bpf_object__load(obj);
  252. if (err)
  253. goto err_out;
  254. *pobj = obj;
  255. *prog_fd = bpf_program__fd(prog);
  256. return 0;
  257. err_out:
  258. bpf_object__close(obj);
  259. return err;
  260. }
  261. int bpf_test_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
  262. size_t insns_cnt, const char *license,
  263. __u32 kern_version, char *log_buf,
  264. size_t log_buf_sz)
  265. {
  266. LIBBPF_OPTS(bpf_prog_load_opts, opts,
  267. .kern_version = kern_version,
  268. .prog_flags = testing_prog_flags(),
  269. .log_level = extra_prog_load_log_flags,
  270. .log_buf = log_buf,
  271. .log_size = log_buf_sz,
  272. );
  273. return bpf_prog_load(type, NULL, license, insns, insns_cnt, &opts);
  274. }
  275. __u64 read_perf_max_sample_freq(void)
  276. {
  277. __u64 sample_freq = 5000; /* fallback to 5000 on error */
  278. FILE *f;
  279. f = fopen("/proc/sys/kernel/perf_event_max_sample_rate", "r");
  280. if (f == NULL) {
  281. printf("Failed to open /proc/sys/kernel/perf_event_max_sample_rate: err %d\n"
  282. "return default value: 5000\n", -errno);
  283. return sample_freq;
  284. }
  285. if (fscanf(f, "%llu", &sample_freq) != 1) {
  286. printf("Failed to parse /proc/sys/kernel/perf_event_max_sample_rate: err %d\n"
  287. "return default value: 5000\n", -errno);
  288. }
  289. fclose(f);
  290. return sample_freq;
  291. }
  292. int finit_module(int fd, const char *param_values, int flags)
  293. {
  294. return syscall(__NR_finit_module, fd, param_values, flags);
  295. }
  296. int delete_module(const char *name, int flags)
  297. {
  298. return syscall(__NR_delete_module, name, flags);
  299. }
  300. int unload_module(const char *name, bool verbose)
  301. {
  302. int ret, cnt = 0;
  303. if (kern_sync_rcu())
  304. fprintf(stdout, "Failed to trigger kernel-side RCU sync!\n");
  305. for (;;) {
  306. ret = delete_module(name, 0);
  307. if (!ret || errno != EAGAIN)
  308. break;
  309. if (++cnt > 10000) {
  310. fprintf(stdout, "Unload of %s timed out\n", name);
  311. break;
  312. }
  313. usleep(100);
  314. }
  315. if (ret) {
  316. if (errno == ENOENT) {
  317. if (verbose)
  318. fprintf(stdout, "%s.ko is already unloaded.\n", name);
  319. return -1;
  320. }
  321. fprintf(stdout, "Failed to unload %s.ko from kernel: %d\n", name, -errno);
  322. return -1;
  323. }
  324. if (verbose)
  325. fprintf(stdout, "Successfully unloaded %s.ko.\n", name);
  326. return 0;
  327. }
  328. int load_module(const char *path, bool verbose)
  329. {
  330. int fd;
  331. if (verbose)
  332. fprintf(stdout, "Loading %s...\n", path);
  333. fd = open(path, O_RDONLY);
  334. if (fd < 0) {
  335. fprintf(stdout, "Can't find %s kernel module: %d\n", path, -errno);
  336. return -ENOENT;
  337. }
  338. if (finit_module(fd, "", 0)) {
  339. fprintf(stdout, "Failed to load %s into the kernel: %d\n", path, -errno);
  340. close(fd);
  341. return -EINVAL;
  342. }
  343. close(fd);
  344. if (verbose)
  345. fprintf(stdout, "Successfully loaded %s.\n", path);
  346. return 0;
  347. }
  348. int unload_bpf_testmod(bool verbose)
  349. {
  350. return unload_module("bpf_testmod", verbose);
  351. }
  352. int load_bpf_testmod(bool verbose)
  353. {
  354. return load_module("bpf_testmod.ko", verbose);
  355. }
  356. /*
  357. * Trigger synchronize_rcu() in kernel.
  358. */
  359. int kern_sync_rcu(void)
  360. {
  361. return syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0, 0);
  362. }
  363. int get_xlated_program(int fd_prog, struct bpf_insn **buf, __u32 *cnt)
  364. {
  365. __u32 buf_element_size = sizeof(struct bpf_insn);
  366. struct bpf_prog_info info = {};
  367. __u32 info_len = sizeof(info);
  368. __u32 xlated_prog_len;
  369. if (bpf_prog_get_info_by_fd(fd_prog, &info, &info_len)) {
  370. perror("bpf_prog_get_info_by_fd failed");
  371. return -1;
  372. }
  373. xlated_prog_len = info.xlated_prog_len;
  374. if (xlated_prog_len % buf_element_size) {
  375. printf("Program length %u is not multiple of %u\n",
  376. xlated_prog_len, buf_element_size);
  377. return -1;
  378. }
  379. *cnt = xlated_prog_len / buf_element_size;
  380. *buf = calloc(*cnt, buf_element_size);
  381. if (!*buf) {
  382. perror("can't allocate xlated program buffer");
  383. return -ENOMEM;
  384. }
  385. bzero(&info, sizeof(info));
  386. info.xlated_prog_len = xlated_prog_len;
  387. info.xlated_prog_insns = (__u64)(unsigned long)*buf;
  388. if (bpf_prog_get_info_by_fd(fd_prog, &info, &info_len)) {
  389. perror("second bpf_prog_get_info_by_fd failed");
  390. goto out_free_buf;
  391. }
  392. return 0;
  393. out_free_buf:
  394. free(*buf);
  395. *buf = NULL;
  396. return -1;
  397. }
  398. bool is_jit_enabled(void)
  399. {
  400. const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
  401. bool enabled = false;
  402. int sysctl_fd;
  403. sysctl_fd = open(jit_sysctl, O_RDONLY);
  404. if (sysctl_fd != -1) {
  405. char tmpc;
  406. if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1)
  407. enabled = (tmpc != '0');
  408. close(sysctl_fd);
  409. }
  410. return enabled;
  411. }