xref: /aosp_15_r20/system/bpf/loader/BpfLoadTest.cpp (revision 55039e042b8390f50b0bdd70c11a2419f6d8fd50)
1  /*
2   * Copyright (C) 2018 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  #include <android-base/file.h>
18  #include <android-base/macros.h>
19  #include <gtest/gtest.h>
20  #include <libbpf.h>
21  #include <stdlib.h>
22  #include <unistd.h>
23  #include <iostream>
24  #include "bpf/BpfMap.h"
25  #include "bpf/BpfUtils.h"
26  #include "include/libbpf_android.h"
27  
28  namespace android {
29  namespace bpf {
30  
31  class BpfLoadTest : public ::testing::Test {
32    protected:
BpfLoadTest()33      BpfLoadTest() {}
34      int mProgFd;
35      std::string mTpProgPath;
36      std::string mTpNeverLoadProgPath;
37      std::string mTpMapPath;
38  
SetUp()39      void SetUp() {
40          /*
41           * b/326156952
42           *
43           * Kernels prior to 5.11 used rlimit memlock accounting for bpf memory
44           * allocations, and therefore require increasing the rlimit of this
45           * process for the maps to be created successfully.
46           *
47           * 5.11 introduces cgroup-based accounting as discussed here:
48           * https://lore.kernel.org/bpf/20201201215900.3569844-1-guro@fb.com/
49           */
50          if (!isAtLeastKernelVersion(5, 11, 0)) EXPECT_EQ(setrlimitForTest(), 0);
51  
52          mTpProgPath = "/sys/fs/bpf/prog_bpfLoadTpProg_tracepoint_sched_sched_switch";
53          unlink(mTpProgPath.c_str());
54  
55          mTpNeverLoadProgPath = "/sys/fs/bpf/prog_bpfLoadTpProg_tracepoint_sched_sched_wakeup";
56          unlink(mTpNeverLoadProgPath.c_str());
57  
58          mTpMapPath = "/sys/fs/bpf/map_bpfLoadTpProg_cpu_pid_map";
59          unlink(mTpMapPath.c_str());
60  
61          auto progPath = android::base::GetExecutableDirectory() + "/bpfLoadTpProg.o";
62          bool critical = true;
63  
64          bpf_prog_type kAllowed[] = {
65                  BPF_PROG_TYPE_UNSPEC,
66          };
67  
68          Location loc = {
69              .dir = "",
70              .prefix = "",
71              .allowedProgTypes = kAllowed,
72              .allowedProgTypesLength = arraysize(kAllowed),
73          };
74          EXPECT_EQ(android::bpf::loadProg(progPath.c_str(), &critical, loc), -1);
75  
76          ASSERT_EQ(android::bpf::loadProg(progPath.c_str(), &critical), 0);
77          EXPECT_EQ(false, critical);
78  
79          mProgFd = retrieveProgram(mTpProgPath.c_str());
80          ASSERT_GT(mProgFd, 0);
81  
82          int ret = bpf_attach_tracepoint(mProgFd, "sched", "sched_switch");
83          EXPECT_NE(ret, 0);
84      }
85  
TearDown()86      void TearDown() {
87          close(mProgFd);
88          unlink(mTpProgPath.c_str());
89          unlink(mTpMapPath.c_str());
90      }
91  
checkMapNonZero()92      void checkMapNonZero() {
93          // The test program installs a tracepoint on sched:sched_switch
94          // and expects the kernel to populate a PID corresponding to CPU
95          android::bpf::BpfMap<uint32_t, uint32_t> m(mTpMapPath.c_str());
96  
97          // Wait for program to run a little
98          sleep(1);
99  
100          int non_zero = 0;
101          const auto iterFunc = [&non_zero](const uint32_t& key, const uint32_t& val,
102                                            BpfMap<uint32_t, uint32_t>& map) {
103              if (val && !non_zero) {
104                  non_zero = 1;
105              }
106  
107              UNUSED(key);
108              UNUSED(map);
109              return base::Result<void>();
110          };
111  
112          EXPECT_RESULT_OK(m.iterateWithValue(iterFunc));
113          EXPECT_EQ(non_zero, 1);
114      }
115  
checkKernelVersionEnforced()116      void checkKernelVersionEnforced() {
117          ASSERT_EQ(retrieveProgram(mTpNeverLoadProgPath.c_str()), -1);
118          ASSERT_EQ(errno, ENOENT);
119      }
120  };
121  
TEST_F(BpfLoadTest,bpfCheckMap)122  TEST_F(BpfLoadTest, bpfCheckMap) {
123      checkMapNonZero();
124  }
125  
TEST_F(BpfLoadTest,bpfCheckMinKernelVersionEnforced)126  TEST_F(BpfLoadTest, bpfCheckMinKernelVersionEnforced) {
127      checkKernelVersionEnforced();
128  }
129  
130  }  // namespace bpf
131  }  // namespace android
132