12f4a32ccSToke Høiland-Jørgensen // SPDX-License-Identifier: GPL-2.0
22f4a32ccSToke Høiland-Jørgensen
32f4a32ccSToke Høiland-Jørgensen #include <sys/types.h>
42f4a32ccSToke Høiland-Jørgensen #include <sys/stat.h>
52f4a32ccSToke Høiland-Jørgensen #include <unistd.h>
62f4a32ccSToke Høiland-Jørgensen #include <test_progs.h>
72f4a32ccSToke Høiland-Jørgensen
get_map_id(struct bpf_object * obj,const char * name)82f4a32ccSToke Høiland-Jørgensen __u32 get_map_id(struct bpf_object *obj, const char *name)
92f4a32ccSToke Høiland-Jørgensen {
102f4a32ccSToke Høiland-Jørgensen struct bpf_map_info map_info = {};
112f4a32ccSToke Høiland-Jørgensen __u32 map_info_len, duration = 0;
122f4a32ccSToke Høiland-Jørgensen struct bpf_map *map;
132f4a32ccSToke Høiland-Jørgensen int err;
142f4a32ccSToke Høiland-Jørgensen
152f4a32ccSToke Høiland-Jørgensen map_info_len = sizeof(map_info);
162f4a32ccSToke Høiland-Jørgensen
172f4a32ccSToke Høiland-Jørgensen map = bpf_object__find_map_by_name(obj, name);
182f4a32ccSToke Høiland-Jørgensen if (CHECK(!map, "find map", "NULL map"))
192f4a32ccSToke Høiland-Jørgensen return 0;
202f4a32ccSToke Høiland-Jørgensen
21*c5a237a4SIlya Leoshkevich err = bpf_map_get_info_by_fd(bpf_map__fd(map),
222f4a32ccSToke Høiland-Jørgensen &map_info, &map_info_len);
232f4a32ccSToke Høiland-Jørgensen CHECK(err, "get map info", "err %d errno %d", err, errno);
242f4a32ccSToke Høiland-Jørgensen return map_info.id;
252f4a32ccSToke Høiland-Jørgensen }
262f4a32ccSToke Høiland-Jørgensen
test_pinning(void)272f4a32ccSToke Høiland-Jørgensen void test_pinning(void)
282f4a32ccSToke Høiland-Jørgensen {
29afef88e6SDaniel Müller const char *file_invalid = "./test_pinning_invalid.bpf.o";
302f4a32ccSToke Høiland-Jørgensen const char *custpinpath = "/sys/fs/bpf/custom/pinmap";
312f4a32ccSToke Høiland-Jørgensen const char *nopinpath = "/sys/fs/bpf/nopinmap";
322f4a32ccSToke Høiland-Jørgensen const char *nopinpath2 = "/sys/fs/bpf/nopinmap2";
332f4a32ccSToke Høiland-Jørgensen const char *custpath = "/sys/fs/bpf/custom";
342f4a32ccSToke Høiland-Jørgensen const char *pinpath = "/sys/fs/bpf/pinmap";
35afef88e6SDaniel Müller const char *file = "./test_pinning.bpf.o";
362f4a32ccSToke Høiland-Jørgensen __u32 map_id, map_id2, duration = 0;
372f4a32ccSToke Høiland-Jørgensen struct stat statbuf = {};
382f4a32ccSToke Høiland-Jørgensen struct bpf_object *obj;
392f4a32ccSToke Høiland-Jørgensen struct bpf_map *map;
4044c4aa2bSHangbin Liu int err, map_fd;
412f4a32ccSToke Høiland-Jørgensen DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,
422f4a32ccSToke Høiland-Jørgensen .pin_root_path = custpath,
432f4a32ccSToke Høiland-Jørgensen );
442f4a32ccSToke Høiland-Jørgensen
452f4a32ccSToke Høiland-Jørgensen /* check that opening fails with invalid pinning value in map def */
462f4a32ccSToke Høiland-Jørgensen obj = bpf_object__open_file(file_invalid, NULL);
472f4a32ccSToke Høiland-Jørgensen err = libbpf_get_error(obj);
482f4a32ccSToke Høiland-Jørgensen if (CHECK(err != -EINVAL, "invalid open", "err %d errno %d\n", err, errno)) {
492f4a32ccSToke Høiland-Jørgensen obj = NULL;
502f4a32ccSToke Høiland-Jørgensen goto out;
512f4a32ccSToke Høiland-Jørgensen }
522f4a32ccSToke Høiland-Jørgensen
532f4a32ccSToke Høiland-Jørgensen /* open the valid object file */
542f4a32ccSToke Høiland-Jørgensen obj = bpf_object__open_file(file, NULL);
552f4a32ccSToke Høiland-Jørgensen err = libbpf_get_error(obj);
562f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) {
572f4a32ccSToke Høiland-Jørgensen obj = NULL;
582f4a32ccSToke Høiland-Jørgensen goto out;
592f4a32ccSToke Høiland-Jørgensen }
602f4a32ccSToke Høiland-Jørgensen
612f4a32ccSToke Høiland-Jørgensen err = bpf_object__load(obj);
622f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "default load", "err %d errno %d\n", err, errno))
632f4a32ccSToke Høiland-Jørgensen goto out;
642f4a32ccSToke Høiland-Jørgensen
652f4a32ccSToke Høiland-Jørgensen /* check that pinmap was pinned */
662f4a32ccSToke Høiland-Jørgensen err = stat(pinpath, &statbuf);
672f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "stat pinpath", "err %d errno %d\n", err, errno))
682f4a32ccSToke Høiland-Jørgensen goto out;
692f4a32ccSToke Høiland-Jørgensen
702f4a32ccSToke Høiland-Jørgensen /* check that nopinmap was *not* pinned */
712f4a32ccSToke Høiland-Jørgensen err = stat(nopinpath, &statbuf);
722f4a32ccSToke Høiland-Jørgensen if (CHECK(!err || errno != ENOENT, "stat nopinpath",
732f4a32ccSToke Høiland-Jørgensen "err %d errno %d\n", err, errno))
742f4a32ccSToke Høiland-Jørgensen goto out;
752f4a32ccSToke Høiland-Jørgensen
762f4a32ccSToke Høiland-Jørgensen /* check that nopinmap2 was *not* pinned */
772f4a32ccSToke Høiland-Jørgensen err = stat(nopinpath2, &statbuf);
782f4a32ccSToke Høiland-Jørgensen if (CHECK(!err || errno != ENOENT, "stat nopinpath2",
792f4a32ccSToke Høiland-Jørgensen "err %d errno %d\n", err, errno))
802f4a32ccSToke Høiland-Jørgensen goto out;
812f4a32ccSToke Høiland-Jørgensen
822f4a32ccSToke Høiland-Jørgensen map_id = get_map_id(obj, "pinmap");
832f4a32ccSToke Høiland-Jørgensen if (!map_id)
842f4a32ccSToke Høiland-Jørgensen goto out;
852f4a32ccSToke Høiland-Jørgensen
862f4a32ccSToke Høiland-Jørgensen bpf_object__close(obj);
872f4a32ccSToke Høiland-Jørgensen
882f4a32ccSToke Høiland-Jørgensen obj = bpf_object__open_file(file, NULL);
892f4a32ccSToke Høiland-Jørgensen if (CHECK_FAIL(libbpf_get_error(obj))) {
902f4a32ccSToke Høiland-Jørgensen obj = NULL;
912f4a32ccSToke Høiland-Jørgensen goto out;
922f4a32ccSToke Høiland-Jørgensen }
932f4a32ccSToke Høiland-Jørgensen
942f4a32ccSToke Høiland-Jørgensen err = bpf_object__load(obj);
952f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "default load", "err %d errno %d\n", err, errno))
962f4a32ccSToke Høiland-Jørgensen goto out;
972f4a32ccSToke Høiland-Jørgensen
982f4a32ccSToke Høiland-Jørgensen /* check that same map ID was reused for second load */
992f4a32ccSToke Høiland-Jørgensen map_id2 = get_map_id(obj, "pinmap");
1002f4a32ccSToke Høiland-Jørgensen if (CHECK(map_id != map_id2, "check reuse",
1012f4a32ccSToke Høiland-Jørgensen "err %d errno %d id %d id2 %d\n", err, errno, map_id, map_id2))
1022f4a32ccSToke Høiland-Jørgensen goto out;
1032f4a32ccSToke Høiland-Jørgensen
1042f4a32ccSToke Høiland-Jørgensen /* should be no-op to re-pin same map */
1052f4a32ccSToke Høiland-Jørgensen map = bpf_object__find_map_by_name(obj, "pinmap");
1062f4a32ccSToke Høiland-Jørgensen if (CHECK(!map, "find map", "NULL map"))
1072f4a32ccSToke Høiland-Jørgensen goto out;
1082f4a32ccSToke Høiland-Jørgensen
1092f4a32ccSToke Høiland-Jørgensen err = bpf_map__pin(map, NULL);
1102f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "re-pin map", "err %d errno %d\n", err, errno))
1112f4a32ccSToke Høiland-Jørgensen goto out;
1122f4a32ccSToke Høiland-Jørgensen
1132f4a32ccSToke Høiland-Jørgensen /* but error to pin at different location */
1142f4a32ccSToke Høiland-Jørgensen err = bpf_map__pin(map, "/sys/fs/bpf/other");
1152f4a32ccSToke Høiland-Jørgensen if (CHECK(!err, "pin map different", "err %d errno %d\n", err, errno))
1162f4a32ccSToke Høiland-Jørgensen goto out;
1172f4a32ccSToke Høiland-Jørgensen
1182f4a32ccSToke Høiland-Jørgensen /* unpin maps with a pin_path set */
1192f4a32ccSToke Høiland-Jørgensen err = bpf_object__unpin_maps(obj, NULL);
1202f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "unpin maps", "err %d errno %d\n", err, errno))
1212f4a32ccSToke Høiland-Jørgensen goto out;
1222f4a32ccSToke Høiland-Jørgensen
1232f4a32ccSToke Høiland-Jørgensen /* and re-pin them... */
1242f4a32ccSToke Høiland-Jørgensen err = bpf_object__pin_maps(obj, NULL);
1252f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "pin maps", "err %d errno %d\n", err, errno))
1262f4a32ccSToke Høiland-Jørgensen goto out;
1272f4a32ccSToke Høiland-Jørgensen
128e244d34dSEvgeniy Litvinenko /* get pinning path */
129e244d34dSEvgeniy Litvinenko if (!ASSERT_STREQ(bpf_map__pin_path(map), pinpath, "get pin path"))
130e244d34dSEvgeniy Litvinenko goto out;
131e244d34dSEvgeniy Litvinenko
1322f4a32ccSToke Høiland-Jørgensen /* set pinning path of other map and re-pin all */
1332f4a32ccSToke Høiland-Jørgensen map = bpf_object__find_map_by_name(obj, "nopinmap");
1342f4a32ccSToke Høiland-Jørgensen if (CHECK(!map, "find map", "NULL map"))
1352f4a32ccSToke Høiland-Jørgensen goto out;
1362f4a32ccSToke Høiland-Jørgensen
1372f4a32ccSToke Høiland-Jørgensen err = bpf_map__set_pin_path(map, custpinpath);
1382f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno))
1392f4a32ccSToke Høiland-Jørgensen goto out;
1402f4a32ccSToke Høiland-Jørgensen
141e244d34dSEvgeniy Litvinenko /* get pinning path after set */
142e244d34dSEvgeniy Litvinenko if (!ASSERT_STREQ(bpf_map__pin_path(map), custpinpath,
143e244d34dSEvgeniy Litvinenko "get pin path after set"))
144e244d34dSEvgeniy Litvinenko goto out;
145e244d34dSEvgeniy Litvinenko
1462f4a32ccSToke Høiland-Jørgensen /* should only pin the one unpinned map */
1472f4a32ccSToke Høiland-Jørgensen err = bpf_object__pin_maps(obj, NULL);
1482f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "pin maps", "err %d errno %d\n", err, errno))
1492f4a32ccSToke Høiland-Jørgensen goto out;
1502f4a32ccSToke Høiland-Jørgensen
1512f4a32ccSToke Høiland-Jørgensen /* check that nopinmap was pinned at the custom path */
1522f4a32ccSToke Høiland-Jørgensen err = stat(custpinpath, &statbuf);
1532f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno))
1542f4a32ccSToke Høiland-Jørgensen goto out;
1552f4a32ccSToke Høiland-Jørgensen
1562f4a32ccSToke Høiland-Jørgensen /* remove the custom pin path to re-test it with auto-pinning below */
1572f4a32ccSToke Høiland-Jørgensen err = unlink(custpinpath);
1582f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "unlink custpinpath", "err %d errno %d\n", err, errno))
1592f4a32ccSToke Høiland-Jørgensen goto out;
1602f4a32ccSToke Høiland-Jørgensen
1612f4a32ccSToke Høiland-Jørgensen err = rmdir(custpath);
1622f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "rmdir custpindir", "err %d errno %d\n", err, errno))
1632f4a32ccSToke Høiland-Jørgensen goto out;
1642f4a32ccSToke Høiland-Jørgensen
1652f4a32ccSToke Høiland-Jørgensen bpf_object__close(obj);
1662f4a32ccSToke Høiland-Jørgensen
1672f4a32ccSToke Høiland-Jørgensen /* open the valid object file again */
1682f4a32ccSToke Høiland-Jørgensen obj = bpf_object__open_file(file, NULL);
1692f4a32ccSToke Høiland-Jørgensen err = libbpf_get_error(obj);
1702f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) {
1712f4a32ccSToke Høiland-Jørgensen obj = NULL;
1722f4a32ccSToke Høiland-Jørgensen goto out;
1732f4a32ccSToke Høiland-Jørgensen }
1742f4a32ccSToke Høiland-Jørgensen
1759c4e395aSToke Høiland-Jørgensen /* set pin paths so that nopinmap2 will attempt to reuse the map at
1769c4e395aSToke Høiland-Jørgensen * pinpath (which will fail), but not before pinmap has already been
1779c4e395aSToke Høiland-Jørgensen * reused
1789c4e395aSToke Høiland-Jørgensen */
1792f4a32ccSToke Høiland-Jørgensen bpf_object__for_each_map(map, obj) {
1802f4a32ccSToke Høiland-Jørgensen if (!strcmp(bpf_map__name(map), "nopinmap"))
1819c4e395aSToke Høiland-Jørgensen err = bpf_map__set_pin_path(map, nopinpath2);
1829c4e395aSToke Høiland-Jørgensen else if (!strcmp(bpf_map__name(map), "nopinmap2"))
1832f4a32ccSToke Høiland-Jørgensen err = bpf_map__set_pin_path(map, pinpath);
1842f4a32ccSToke Høiland-Jørgensen else
1852f4a32ccSToke Høiland-Jørgensen continue;
1862f4a32ccSToke Høiland-Jørgensen
1872f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno))
1882f4a32ccSToke Høiland-Jørgensen goto out;
1892f4a32ccSToke Høiland-Jørgensen }
1902f4a32ccSToke Høiland-Jørgensen
1912f4a32ccSToke Høiland-Jørgensen /* should fail because of map parameter mismatch */
1922f4a32ccSToke Høiland-Jørgensen err = bpf_object__load(obj);
1932f4a32ccSToke Høiland-Jørgensen if (CHECK(err != -EINVAL, "param mismatch load", "err %d errno %d\n", err, errno))
1942f4a32ccSToke Høiland-Jørgensen goto out;
1952f4a32ccSToke Høiland-Jørgensen
1969c4e395aSToke Høiland-Jørgensen /* nopinmap2 should have been pinned and cleaned up again */
1979c4e395aSToke Høiland-Jørgensen err = stat(nopinpath2, &statbuf);
1989c4e395aSToke Høiland-Jørgensen if (CHECK(!err || errno != ENOENT, "stat nopinpath2",
1999c4e395aSToke Høiland-Jørgensen "err %d errno %d\n", err, errno))
2009c4e395aSToke Høiland-Jørgensen goto out;
2019c4e395aSToke Høiland-Jørgensen
2029c4e395aSToke Høiland-Jørgensen /* pinmap should still be there */
2039c4e395aSToke Høiland-Jørgensen err = stat(pinpath, &statbuf);
2049c4e395aSToke Høiland-Jørgensen if (CHECK(err, "stat pinpath", "err %d errno %d\n", err, errno))
2059c4e395aSToke Høiland-Jørgensen goto out;
2069c4e395aSToke Høiland-Jørgensen
2072f4a32ccSToke Høiland-Jørgensen bpf_object__close(obj);
2082f4a32ccSToke Høiland-Jørgensen
2092f4a32ccSToke Høiland-Jørgensen /* test auto-pinning at custom path with open opt */
2102f4a32ccSToke Høiland-Jørgensen obj = bpf_object__open_file(file, &opts);
2112f4a32ccSToke Høiland-Jørgensen if (CHECK_FAIL(libbpf_get_error(obj))) {
2122f4a32ccSToke Høiland-Jørgensen obj = NULL;
2132f4a32ccSToke Høiland-Jørgensen goto out;
2142f4a32ccSToke Høiland-Jørgensen }
2152f4a32ccSToke Høiland-Jørgensen
2162f4a32ccSToke Høiland-Jørgensen err = bpf_object__load(obj);
2172f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "custom load", "err %d errno %d\n", err, errno))
2182f4a32ccSToke Høiland-Jørgensen goto out;
2192f4a32ccSToke Høiland-Jørgensen
2202f4a32ccSToke Høiland-Jørgensen /* check that pinmap was pinned at the custom path */
2212f4a32ccSToke Høiland-Jørgensen err = stat(custpinpath, &statbuf);
2222f4a32ccSToke Høiland-Jørgensen if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno))
2232f4a32ccSToke Høiland-Jørgensen goto out;
2242f4a32ccSToke Høiland-Jørgensen
22544c4aa2bSHangbin Liu /* remove the custom pin path to re-test it with reuse fd below */
22644c4aa2bSHangbin Liu err = unlink(custpinpath);
22744c4aa2bSHangbin Liu if (CHECK(err, "unlink custpinpath", "err %d errno %d\n", err, errno))
22844c4aa2bSHangbin Liu goto out;
22944c4aa2bSHangbin Liu
23044c4aa2bSHangbin Liu err = rmdir(custpath);
23144c4aa2bSHangbin Liu if (CHECK(err, "rmdir custpindir", "err %d errno %d\n", err, errno))
23244c4aa2bSHangbin Liu goto out;
23344c4aa2bSHangbin Liu
23444c4aa2bSHangbin Liu bpf_object__close(obj);
23544c4aa2bSHangbin Liu
23644c4aa2bSHangbin Liu /* test pinning at custom path with reuse fd */
23744c4aa2bSHangbin Liu obj = bpf_object__open_file(file, NULL);
23844c4aa2bSHangbin Liu err = libbpf_get_error(obj);
23944c4aa2bSHangbin Liu if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) {
24044c4aa2bSHangbin Liu obj = NULL;
24144c4aa2bSHangbin Liu goto out;
24244c4aa2bSHangbin Liu }
24344c4aa2bSHangbin Liu
2442fe256a4SAndrii Nakryiko map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, sizeof(__u32),
2452fe256a4SAndrii Nakryiko sizeof(__u64), 1, NULL);
24644c4aa2bSHangbin Liu if (CHECK(map_fd < 0, "create pinmap manually", "fd %d\n", map_fd))
24744c4aa2bSHangbin Liu goto out;
24844c4aa2bSHangbin Liu
24944c4aa2bSHangbin Liu map = bpf_object__find_map_by_name(obj, "pinmap");
25044c4aa2bSHangbin Liu if (CHECK(!map, "find map", "NULL map"))
25144c4aa2bSHangbin Liu goto close_map_fd;
25244c4aa2bSHangbin Liu
25344c4aa2bSHangbin Liu err = bpf_map__reuse_fd(map, map_fd);
25444c4aa2bSHangbin Liu if (CHECK(err, "reuse pinmap fd", "err %d errno %d\n", err, errno))
25544c4aa2bSHangbin Liu goto close_map_fd;
25644c4aa2bSHangbin Liu
25744c4aa2bSHangbin Liu err = bpf_map__set_pin_path(map, custpinpath);
25844c4aa2bSHangbin Liu if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno))
25944c4aa2bSHangbin Liu goto close_map_fd;
26044c4aa2bSHangbin Liu
26144c4aa2bSHangbin Liu err = bpf_object__load(obj);
26244c4aa2bSHangbin Liu if (CHECK(err, "custom load", "err %d errno %d\n", err, errno))
26344c4aa2bSHangbin Liu goto close_map_fd;
26444c4aa2bSHangbin Liu
26544c4aa2bSHangbin Liu /* check that pinmap was pinned at the custom path */
26644c4aa2bSHangbin Liu err = stat(custpinpath, &statbuf);
26744c4aa2bSHangbin Liu if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno))
26844c4aa2bSHangbin Liu goto close_map_fd;
26944c4aa2bSHangbin Liu
27044c4aa2bSHangbin Liu close_map_fd:
27144c4aa2bSHangbin Liu close(map_fd);
2722f4a32ccSToke Høiland-Jørgensen out:
2732f4a32ccSToke Høiland-Jørgensen unlink(pinpath);
2742f4a32ccSToke Høiland-Jørgensen unlink(nopinpath);
2752f4a32ccSToke Høiland-Jørgensen unlink(nopinpath2);
2762f4a32ccSToke Høiland-Jørgensen unlink(custpinpath);
2772f4a32ccSToke Høiland-Jørgensen rmdir(custpath);
2782f4a32ccSToke Høiland-Jørgensen if (obj)
2792f4a32ccSToke Høiland-Jørgensen bpf_object__close(obj);
2802f4a32ccSToke Høiland-Jørgensen }
281