testing_helpers.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  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. free(buf);
  173. fclose(f);
  174. return err;
  175. }
  176. int parse_test_list(const char *s,
  177. struct test_filter_set *set,
  178. bool is_glob_pattern)
  179. {
  180. char *input, *state = NULL, *test_spec;
  181. int err = 0, cnt = 0;
  182. input = strdup(s);
  183. if (!input)
  184. return -ENOMEM;
  185. while ((test_spec = strtok_r(cnt++ ? NULL : input, ",", &state))) {
  186. err = insert_test(set, test_spec, is_glob_pattern);
  187. if (err)
  188. break;
  189. }
  190. free(input);
  191. return err;
  192. }
  193. __u32 link_info_prog_id(const struct bpf_link *link, struct bpf_link_info *info)
  194. {
  195. __u32 info_len = sizeof(*info);
  196. int err;
  197. memset(info, 0, sizeof(*info));
  198. err = bpf_link_get_info_by_fd(bpf_link__fd(link), info, &info_len);
  199. if (err) {
  200. printf("failed to get link info: %d\n", -errno);
  201. return 0;
  202. }
  203. return info->prog_id;
  204. }
  205. int extra_prog_load_log_flags = 0;
  206. int testing_prog_flags(void)
  207. {
  208. static int cached_flags = -1;
  209. static int prog_flags[] = { BPF_F_TEST_RND_HI32, BPF_F_TEST_REG_INVARIANTS };
  210. static struct bpf_insn insns[] = {
  211. BPF_MOV64_IMM(BPF_REG_0, 0),
  212. BPF_EXIT_INSN(),
  213. };
  214. int insn_cnt = ARRAY_SIZE(insns), i, fd, flags = 0;
  215. LIBBPF_OPTS(bpf_prog_load_opts, opts);
  216. if (cached_flags >= 0)
  217. return cached_flags;
  218. for (i = 0; i < ARRAY_SIZE(prog_flags); i++) {
  219. opts.prog_flags = prog_flags[i];
  220. fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, "flag-test", "GPL",
  221. insns, insn_cnt, &opts);
  222. if (fd >= 0) {
  223. flags |= prog_flags[i];
  224. close(fd);
  225. }
  226. }
  227. cached_flags = flags;
  228. return cached_flags;
  229. }
  230. int bpf_prog_test_load(const char *file, enum bpf_prog_type type,
  231. struct bpf_object **pobj, int *prog_fd)
  232. {
  233. LIBBPF_OPTS(bpf_object_open_opts, opts,
  234. .kernel_log_level = extra_prog_load_log_flags,
  235. );
  236. struct bpf_object *obj;
  237. struct bpf_program *prog;
  238. __u32 flags;
  239. int err;
  240. obj = bpf_object__open_file(file, &opts);
  241. if (!obj)
  242. return -errno;
  243. prog = bpf_object__next_program(obj, NULL);
  244. if (!prog) {
  245. err = -ENOENT;
  246. goto err_out;
  247. }
  248. if (type != BPF_PROG_TYPE_UNSPEC && bpf_program__type(prog) != type)
  249. bpf_program__set_type(prog, type);
  250. flags = bpf_program__flags(prog) | testing_prog_flags();
  251. bpf_program__set_flags(prog, flags);
  252. err = bpf_object__load(obj);
  253. if (err)
  254. goto err_out;
  255. *pobj = obj;
  256. *prog_fd = bpf_program__fd(prog);
  257. return 0;
  258. err_out:
  259. bpf_object__close(obj);
  260. return err;
  261. }
  262. int bpf_test_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
  263. size_t insns_cnt, const char *license,
  264. __u32 kern_version, char *log_buf,
  265. size_t log_buf_sz)
  266. {
  267. LIBBPF_OPTS(bpf_prog_load_opts, opts,
  268. .kern_version = kern_version,
  269. .prog_flags = testing_prog_flags(),
  270. .log_level = extra_prog_load_log_flags,
  271. .log_buf = log_buf,
  272. .log_size = log_buf_sz,
  273. );
  274. return bpf_prog_load(type, NULL, license, insns, insns_cnt, &opts);
  275. }
  276. __u64 read_perf_max_sample_freq(void)
  277. {
  278. __u64 sample_freq = 5000; /* fallback to 5000 on error */
  279. FILE *f;
  280. f = fopen("/proc/sys/kernel/perf_event_max_sample_rate", "r");
  281. if (f == NULL) {
  282. printf("Failed to open /proc/sys/kernel/perf_event_max_sample_rate: err %d\n"
  283. "return default value: 5000\n", -errno);
  284. return sample_freq;
  285. }
  286. if (fscanf(f, "%llu", &sample_freq) != 1) {
  287. printf("Failed to parse /proc/sys/kernel/perf_event_max_sample_rate: err %d\n"
  288. "return default value: 5000\n", -errno);
  289. }
  290. fclose(f);
  291. return sample_freq;
  292. }
  293. int finit_module(int fd, const char *param_values, int flags)
  294. {
  295. return syscall(__NR_finit_module, fd, param_values, flags);
  296. }
  297. int delete_module(const char *name, int flags)
  298. {
  299. return syscall(__NR_delete_module, name, flags);
  300. }
  301. int unload_module(const char *name, bool verbose)
  302. {
  303. int ret, cnt = 0;
  304. if (kern_sync_rcu())
  305. fprintf(stdout, "Failed to trigger kernel-side RCU sync!\n");
  306. for (;;) {
  307. ret = delete_module(name, 0);
  308. if (!ret || errno != EAGAIN)
  309. break;
  310. if (++cnt > 10000) {
  311. fprintf(stdout, "Unload of %s timed out\n", name);
  312. break;
  313. }
  314. usleep(100);
  315. }
  316. if (ret) {
  317. if (errno == ENOENT) {
  318. if (verbose)
  319. fprintf(stdout, "%s.ko is already unloaded.\n", name);
  320. return -1;
  321. }
  322. fprintf(stdout, "Failed to unload %s.ko from kernel: %d\n", name, -errno);
  323. return -1;
  324. }
  325. if (verbose)
  326. fprintf(stdout, "Successfully unloaded %s.ko.\n", name);
  327. return 0;
  328. }
  329. static int __load_module(const char *path, const char *param_values, bool verbose)
  330. {
  331. int fd;
  332. if (verbose)
  333. fprintf(stdout, "Loading %s...\n", path);
  334. fd = open(path, O_RDONLY);
  335. if (fd < 0) {
  336. fprintf(stdout, "Can't find %s kernel module: %d\n", path, -errno);
  337. return -ENOENT;
  338. }
  339. if (finit_module(fd, param_values, 0)) {
  340. fprintf(stdout, "Failed to load %s into the kernel: %d\n", path, -errno);
  341. close(fd);
  342. return -EINVAL;
  343. }
  344. close(fd);
  345. if (verbose)
  346. fprintf(stdout, "Successfully loaded %s.\n", path);
  347. return 0;
  348. }
  349. int load_module_params(const char *path, const char *param_values, bool verbose)
  350. {
  351. return __load_module(path, param_values, verbose);
  352. }
  353. int load_module(const char *path, bool verbose)
  354. {
  355. return __load_module(path, "", verbose);
  356. }
  357. int unload_bpf_testmod(bool verbose)
  358. {
  359. return unload_module("bpf_testmod", verbose);
  360. }
  361. int load_bpf_testmod(bool verbose)
  362. {
  363. return load_module("bpf_testmod.ko", verbose);
  364. }
  365. /*
  366. * Trigger synchronize_rcu() in kernel.
  367. */
  368. int kern_sync_rcu(void)
  369. {
  370. return syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0, 0);
  371. }
  372. int get_xlated_program(int fd_prog, struct bpf_insn **buf, __u32 *cnt)
  373. {
  374. __u32 buf_element_size = sizeof(struct bpf_insn);
  375. struct bpf_prog_info info = {};
  376. __u32 info_len = sizeof(info);
  377. __u32 xlated_prog_len;
  378. if (bpf_prog_get_info_by_fd(fd_prog, &info, &info_len)) {
  379. perror("bpf_prog_get_info_by_fd failed");
  380. return -1;
  381. }
  382. xlated_prog_len = info.xlated_prog_len;
  383. if (xlated_prog_len % buf_element_size) {
  384. printf("Program length %u is not multiple of %u\n",
  385. xlated_prog_len, buf_element_size);
  386. return -1;
  387. }
  388. *cnt = xlated_prog_len / buf_element_size;
  389. *buf = calloc(*cnt, buf_element_size);
  390. if (!*buf) {
  391. perror("can't allocate xlated program buffer");
  392. return -ENOMEM;
  393. }
  394. bzero(&info, sizeof(info));
  395. info.xlated_prog_len = xlated_prog_len;
  396. info.xlated_prog_insns = (__u64)(unsigned long)*buf;
  397. if (bpf_prog_get_info_by_fd(fd_prog, &info, &info_len)) {
  398. perror("second bpf_prog_get_info_by_fd failed");
  399. goto out_free_buf;
  400. }
  401. return 0;
  402. out_free_buf:
  403. free(*buf);
  404. *buf = NULL;
  405. return -1;
  406. }
  407. bool is_jit_enabled(void)
  408. {
  409. const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
  410. bool enabled = false;
  411. int sysctl_fd;
  412. sysctl_fd = open(jit_sysctl, O_RDONLY);
  413. if (sysctl_fd != -1) {
  414. char tmpc;
  415. if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1)
  416. enabled = (tmpc != '0');
  417. close(sysctl_fd);
  418. }
  419. return enabled;
  420. }