0001
0002
0003
0004 #include <test_progs.h>
0005
0006 #include "test_btf_map_in_map.skel.h"
0007
0008 static int duration;
0009
0010 static __u32 bpf_map_id(struct bpf_map *map)
0011 {
0012 struct bpf_map_info info;
0013 __u32 info_len = sizeof(info);
0014 int err;
0015
0016 memset(&info, 0, info_len);
0017 err = bpf_obj_get_info_by_fd(bpf_map__fd(map), &info, &info_len);
0018 if (err)
0019 return 0;
0020 return info.id;
0021 }
0022
0023 static void test_lookup_update(void)
0024 {
0025 int map1_fd, map2_fd, map3_fd, map4_fd, map5_fd, map1_id, map2_id;
0026 int outer_arr_fd, outer_hash_fd, outer_arr_dyn_fd;
0027 struct test_btf_map_in_map *skel;
0028 int err, key = 0, val, i, fd;
0029
0030 skel = test_btf_map_in_map__open_and_load();
0031 if (CHECK(!skel, "skel_open", "failed to open&load skeleton\n"))
0032 return;
0033
0034 err = test_btf_map_in_map__attach(skel);
0035 if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err))
0036 goto cleanup;
0037
0038 map1_fd = bpf_map__fd(skel->maps.inner_map1);
0039 map2_fd = bpf_map__fd(skel->maps.inner_map2);
0040 map3_fd = bpf_map__fd(skel->maps.inner_map3);
0041 map4_fd = bpf_map__fd(skel->maps.inner_map4);
0042 map5_fd = bpf_map__fd(skel->maps.inner_map5);
0043 outer_arr_dyn_fd = bpf_map__fd(skel->maps.outer_arr_dyn);
0044 outer_arr_fd = bpf_map__fd(skel->maps.outer_arr);
0045 outer_hash_fd = bpf_map__fd(skel->maps.outer_hash);
0046
0047
0048 bpf_map_update_elem(outer_arr_fd, &key, &map1_fd, 0);
0049 bpf_map_update_elem(outer_hash_fd, &key, &map2_fd, 0);
0050 bpf_map_update_elem(outer_arr_dyn_fd, &key, &map3_fd, 0);
0051 skel->bss->input = 1;
0052 usleep(1);
0053 bpf_map_lookup_elem(map1_fd, &key, &val);
0054 CHECK(val != 1, "inner1", "got %d != exp %d\n", val, 1);
0055 bpf_map_lookup_elem(map2_fd, &key, &val);
0056 CHECK(val != 2, "inner2", "got %d != exp %d\n", val, 2);
0057 bpf_map_lookup_elem(map3_fd, &key, &val);
0058 CHECK(val != 3, "inner3", "got %d != exp %d\n", val, 3);
0059
0060
0061 bpf_map_update_elem(outer_arr_fd, &key, &map2_fd, 0);
0062 bpf_map_update_elem(outer_hash_fd, &key, &map1_fd, 0);
0063 bpf_map_update_elem(outer_arr_dyn_fd, &key, &map4_fd, 0);
0064 skel->bss->input = 3;
0065 usleep(1);
0066 bpf_map_lookup_elem(map1_fd, &key, &val);
0067 CHECK(val != 4, "inner1", "got %d != exp %d\n", val, 4);
0068 bpf_map_lookup_elem(map2_fd, &key, &val);
0069 CHECK(val != 3, "inner2", "got %d != exp %d\n", val, 3);
0070 bpf_map_lookup_elem(map4_fd, &key, &val);
0071 CHECK(val != 5, "inner4", "got %d != exp %d\n", val, 5);
0072
0073
0074 bpf_map_update_elem(outer_arr_dyn_fd, &key, &map5_fd, 0);
0075 skel->bss->input = 5;
0076 usleep(1);
0077 bpf_map_lookup_elem(map5_fd, &key, &val);
0078 CHECK(val != 7, "inner5", "got %d != exp %d\n", val, 7);
0079
0080 for (i = 0; i < 5; i++) {
0081 val = i % 2 ? map1_fd : map2_fd;
0082 err = bpf_map_update_elem(outer_hash_fd, &key, &val, 0);
0083 if (CHECK_FAIL(err)) {
0084 printf("failed to update hash_of_maps on iter #%d\n", i);
0085 goto cleanup;
0086 }
0087 err = bpf_map_update_elem(outer_arr_fd, &key, &val, 0);
0088 if (CHECK_FAIL(err)) {
0089 printf("failed to update array_of_maps on iter #%d\n", i);
0090 goto cleanup;
0091 }
0092 val = i % 2 ? map4_fd : map5_fd;
0093 err = bpf_map_update_elem(outer_arr_dyn_fd, &key, &val, 0);
0094 if (CHECK_FAIL(err)) {
0095 printf("failed to update array_of_maps (dyn) on iter #%d\n", i);
0096 goto cleanup;
0097 }
0098 }
0099
0100 map1_id = bpf_map_id(skel->maps.inner_map1);
0101 map2_id = bpf_map_id(skel->maps.inner_map2);
0102 CHECK(map1_id == 0, "map1_id", "failed to get ID 1\n");
0103 CHECK(map2_id == 0, "map2_id", "failed to get ID 2\n");
0104
0105 test_btf_map_in_map__destroy(skel);
0106 skel = NULL;
0107
0108
0109
0110
0111
0112
0113
0114
0115 CHECK(kern_sync_rcu(), "sync_rcu", "failed\n");
0116 CHECK(kern_sync_rcu(), "sync_rcu", "failed\n");
0117
0118 fd = bpf_map_get_fd_by_id(map1_id);
0119 if (CHECK(fd >= 0, "map1_leak", "inner_map1 leaked!\n")) {
0120 close(fd);
0121 goto cleanup;
0122 }
0123 fd = bpf_map_get_fd_by_id(map2_id);
0124 if (CHECK(fd >= 0, "map2_leak", "inner_map2 leaked!\n")) {
0125 close(fd);
0126 goto cleanup;
0127 }
0128
0129 cleanup:
0130 test_btf_map_in_map__destroy(skel);
0131 }
0132
0133 static void test_diff_size(void)
0134 {
0135 struct test_btf_map_in_map *skel;
0136 int err, inner_map_fd, zero = 0;
0137
0138 skel = test_btf_map_in_map__open_and_load();
0139 if (CHECK(!skel, "skel_open", "failed to open&load skeleton\n"))
0140 return;
0141
0142 inner_map_fd = bpf_map__fd(skel->maps.sockarr_sz2);
0143 err = bpf_map_update_elem(bpf_map__fd(skel->maps.outer_sockarr), &zero,
0144 &inner_map_fd, 0);
0145 CHECK(err, "outer_sockarr inner map size check",
0146 "cannot use a different size inner_map\n");
0147
0148 inner_map_fd = bpf_map__fd(skel->maps.inner_map_sz2);
0149 err = bpf_map_update_elem(bpf_map__fd(skel->maps.outer_arr), &zero,
0150 &inner_map_fd, 0);
0151 CHECK(!err, "outer_arr inner map size check",
0152 "incorrectly updated with a different size inner_map\n");
0153
0154 test_btf_map_in_map__destroy(skel);
0155 }
0156
0157 void test_btf_map_in_map(void)
0158 {
0159 if (test__start_subtest("lookup_update"))
0160 test_lookup_update();
0161
0162 if (test__start_subtest("diff_size"))
0163 test_diff_size();
0164 }