| @@ -837,6 +837,132 @@ static void test_tp_attach_query(void) · 836 unmodified lines |
| 837 | free(query); | 837 | free(query); |
| 838 | } | 838 | } |
| 839 | | 839 | |
| | 840 | static int compare_map_keys(int map1_fd, int map2_fd) |
| | 841 | { |
| | 842 | __u32 key, next_key; |
| | 843 | char val_buf[PERF_MAX_STACK_DEPTH * sizeof(__u64)]; |
| | 844 | int err; |
| | 845 | |
| | 846 | err = bpf_map_get_next_key(map1_fd, NULL, &key); |
| | 847 | if (err) |
| | 848 | return err; |
| | 849 | err = bpf_map_lookup_elem(map2_fd, &key, val_buf); |
| | 850 | if (err) |
| | 851 | return err; |
| | 852 | |
| | 853 | while (bpf_map_get_next_key(map1_fd, &key, &next_key) == 0) { |
| | 854 | err = bpf_map_lookup_elem(map2_fd, &next_key, val_buf); |
| | 855 | if (err) |
| | 856 | return err; |
| | 857 | |
| | 858 | key = next_key; |
| | 859 | } |
| | 860 | if (errno != ENOENT) |
| | 861 | return -1; |
| | 862 | |
| | 863 | return 0; |
| | 864 | } |
| | 865 | |
| | 866 | static void test_stacktrace_map() |
| | 867 | { |
| | 868 | int control_map_fd, stackid_hmap_fd, stackmap_fd; |
| | 869 | const char *file = "./test_stacktrace_map.o"; |
| | 870 | int bytes, efd, err, pmu_fd, prog_fd; |
| | 871 | struct perf_event_attr attr = {}; |
| | 872 | __u32 key, val, duration = 0; |
| | 873 | struct bpf_object *obj; |
| | 874 | char buf[256]; |
| | 875 | |
| | 876 | err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd); |
| | 877 | if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno)) |
| | 878 | goto out; |
| | 879 | |
| | 880 | /* Get the ID for the sched/sched_switch tracepoint */ |
| | 881 | snprintf(buf, sizeof(buf), |
| | 882 | "/sys/kernel/debug/tracing/events/sched/sched_switch/id"); |
| | 883 | efd = open(buf, O_RDONLY, 0); |
| | 884 | if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno)) |
| | 885 | goto close_prog; |
| | 886 | |
| | 887 | bytes = read(efd, buf, sizeof(buf)); |
| | 888 | close(efd); |
| | 889 | if (CHECK(bytes <= 0 || bytes >= sizeof(buf), |
| | 890 | "read", "bytes %d errno %d\n", bytes, errno)) |
| | 891 | goto close_prog; |
| | 892 | |
| | 893 | /* Open the perf event and attach bpf progrram */ |
| | 894 | attr.config = strtol(buf, NULL, 0); |
| | 895 | attr.type = PERF_TYPE_TRACEPOINT; |
| | 896 | attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN; |
| | 897 | attr.sample_period = 1; |
| | 898 | attr.wakeup_events = 1; |
| | 899 | pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */, |
| | 900 | 0 /* cpu 0 */, -1 /* group id */, |
| | 901 | 0 /* flags */); |
| | 902 | if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n", |
| | 903 | pmu_fd, errno)) |
| | 904 | goto close_prog; |
| | 905 | |
| | 906 | err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0); |
| | 907 | if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n", |
| | 908 | err, errno)) |
| | 909 | goto close_pmu; |
| | 910 | |
| | 911 | err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd); |
| | 912 | if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n", |
| | 913 | err, errno)) |
| | 914 | goto disable_pmu; |
| | 915 | |
| | 916 | /* find map fds */ |
| | 917 | control_map_fd = bpf_find_map(__func__, obj, "control_map"); |
| | 918 | if (CHECK(control_map_fd < 0, "bpf_find_map control_map", |
| | 919 | "err %d errno %d\n", err, errno)) |
| | 920 | goto disable_pmu; |
| | 921 | |
| | 922 | stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap"); |
| | 923 | if (CHECK(stackid_hmap_fd < 0, "bpf_find_map stackid_hmap", |
| | 924 | "err %d errno %d\n", err, errno)) |
| | 925 | goto disable_pmu; |
| | 926 | |
| | 927 | stackmap_fd = bpf_find_map(__func__, obj, "stackmap"); |
| | 928 | if (CHECK(stackmap_fd < 0, "bpf_find_map stackmap", "err %d errno %d\n", |
| | 929 | err, errno)) |
| | 930 | goto disable_pmu; |
| | 931 | |
| | 932 | /* give some time for bpf program run */ |
| | 933 | sleep(1); |
| | 934 | |
| | 935 | /* disable stack trace collection */ |
| | 936 | key = 0; |
| | 937 | val = 1; |
| | 938 | bpf_map_update_elem(control_map_fd, &key, &val, 0); |
| | 939 | |
| | 940 | /* for every element in stackid_hmap, we can find a corresponding one |
| | 941 | * in stackmap, and vise versa. |
| | 942 | */ |
| | 943 | err = compare_map_keys(stackid_hmap_fd, stackmap_fd); |
| | 944 | if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap", |
| | 945 | "err %d errno %d\n", err, errno)) |
| | 946 | goto disable_pmu; |
| | 947 | |
| | 948 | err = compare_map_keys(stackmap_fd, stackid_hmap_fd); |
| | 949 | if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap", |
| | 950 | "err %d errno %d\n", err, errno)) |
| | 951 | ; /* fall through */ |
| | 952 | |
| | 953 | disable_pmu: |
| | 954 | ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE); |
| | 955 | |
| | 956 | close_pmu: |
| | 957 | close(pmu_fd); |
| | 958 | |
| | 959 | close_prog: |
| | 960 | bpf_object__close(obj); |
| | 961 | |
| | 962 | out: |
| | 963 | return; |
| | 964 | } |
| | 965 | |
| 840 | int main(void) | 966 | int main(void) |
| 841 | { | 967 | { |
| 842 | struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY }; | 968 | struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY }; |
| @@ -852,6 +978,7 @@ int main(void) · 9 unmodified lines |
| 852 | test_pkt_md_access(); | 978 | test_pkt_md_access(); |
| 853 | test_obj_name(); | 979 | test_obj_name(); |
| 854 | test_tp_attach_query(); | 980 | test_tp_attach_query(); |
| | 981 | test_stacktrace_map(); |
| 855 | | 982 | |
| 856 | printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); | 983 | printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); |
| 857 | return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; | 984 | return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; |