| // SPDX-License-Identifier: GPL-2.0-only |
| /* Copyright (c) 2017 Facebook |
| */ |
| #include "test_progs.h" |
| #include "bpf_rlimit.h" |
| |
| int error_cnt, pass_cnt; |
| bool jit_enabled; |
| bool verifier_stats = false; |
| |
| struct ipv4_packet pkt_v4 = { |
| .eth.h_proto = __bpf_constant_htons(ETH_P_IP), |
| .iph.ihl = 5, |
| .iph.protocol = IPPROTO_TCP, |
| .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), |
| .tcp.urg_ptr = 123, |
| .tcp.doff = 5, |
| }; |
| |
| struct ipv6_packet pkt_v6 = { |
| .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6), |
| .iph.nexthdr = IPPROTO_TCP, |
| .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), |
| .tcp.urg_ptr = 123, |
| .tcp.doff = 5, |
| }; |
| |
| 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); |
| error_cnt++; |
| return -1; |
| } |
| return bpf_map__fd(map); |
| } |
| |
| static bool is_jit_enabled(void) |
| { |
| const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable"; |
| bool enabled = false; |
| int sysctl_fd; |
| |
| sysctl_fd = open(jit_sysctl, 0, O_RDONLY); |
| if (sysctl_fd != -1) { |
| char tmpc; |
| |
| if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1) |
| enabled = (tmpc != '0'); |
| close(sysctl_fd); |
| } |
| |
| return enabled; |
| } |
| |
| int compare_map_keys(int map1_fd, int map2_fd) |
| { |
| __u32 key, next_key; |
| char val_buf[PERF_MAX_STACK_DEPTH * |
| sizeof(struct bpf_stack_build_id)]; |
| int err; |
| |
| err = bpf_map_get_next_key(map1_fd, NULL, &key); |
| if (err) |
| return err; |
| err = bpf_map_lookup_elem(map2_fd, &key, val_buf); |
| if (err) |
| return err; |
| |
| while (bpf_map_get_next_key(map1_fd, &key, &next_key) == 0) { |
| err = bpf_map_lookup_elem(map2_fd, &next_key, val_buf); |
| if (err) |
| return err; |
| |
| key = next_key; |
| } |
| if (errno != ENOENT) |
| return -1; |
| |
| return 0; |
| } |
| |
| int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len) |
| { |
| __u32 key, next_key, *cur_key_p, *next_key_p; |
| char *val_buf1, *val_buf2; |
| int i, err = 0; |
| |
| val_buf1 = malloc(stack_trace_len); |
| val_buf2 = malloc(stack_trace_len); |
| cur_key_p = NULL; |
| next_key_p = &key; |
| while (bpf_map_get_next_key(smap_fd, cur_key_p, next_key_p) == 0) { |
| err = bpf_map_lookup_elem(smap_fd, next_key_p, val_buf1); |
| if (err) |
| goto out; |
| err = bpf_map_lookup_elem(amap_fd, next_key_p, val_buf2); |
| if (err) |
| goto out; |
| for (i = 0; i < stack_trace_len; i++) { |
| if (val_buf1[i] != val_buf2[i]) { |
| err = -1; |
| goto out; |
| } |
| } |
| key = *next_key_p; |
| cur_key_p = &key; |
| next_key_p = &next_key; |
| } |
| if (errno != ENOENT) |
| err = -1; |
| |
| out: |
| free(val_buf1); |
| free(val_buf2); |
| return err; |
| } |
| |
| int extract_build_id(char *build_id, size_t size) |
| { |
| FILE *fp; |
| char *line = NULL; |
| size_t len = 0; |
| |
| fp = popen("readelf -n ./urandom_read | grep 'Build ID'", "r"); |
| if (fp == NULL) |
| return -1; |
| |
| if (getline(&line, &len, fp) == -1) |
| goto err; |
| fclose(fp); |
| |
| if (len > size) |
| len = size; |
| memcpy(build_id, line, len); |
| build_id[len] = '\0'; |
| return 0; |
| err: |
| fclose(fp); |
| return -1; |
| } |
| |
| void *spin_lock_thread(void *arg) |
| { |
| __u32 duration, retval; |
| int err, prog_fd = *(u32 *) arg; |
| |
| err = bpf_prog_test_run(prog_fd, 10000, &pkt_v4, sizeof(pkt_v4), |
| NULL, NULL, &retval, &duration); |
| CHECK(err || retval, "", |
| "err %d errno %d retval %d duration %d\n", |
| err, errno, retval, duration); |
| pthread_exit(arg); |
| } |
| |
| #define DECLARE |
| #include <prog_tests/tests.h> |
| #undef DECLARE |
| |
| int main(int ac, char **av) |
| { |
| srand(time(NULL)); |
| |
| jit_enabled = is_jit_enabled(); |
| |
| if (ac == 2 && strcmp(av[1], "-s") == 0) |
| verifier_stats = true; |
| |
| #define CALL |
| #include <prog_tests/tests.h> |
| #undef CALL |
| |
| printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); |
| return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; |
| } |