xref: /aosp_15_r20/system/netd/tests/kernel_test.cpp (revision 8542734a0dd1db395a4d42aae09c37f3c3c3e7a1)
1 /*
2  * Copyright (C) 2022 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 
18 #include <unistd.h>
19 
20 #include <gtest/gtest.h>
21 #include <vintf/VintfObject.h>
22 
23 #include <fstream>
24 #include <string>
25 
26 #include "bpf/KernelUtils.h"
27 
28 namespace android {
29 namespace net {
30 
31 namespace {
32 
33 using ::android::vintf::RuntimeInfo;
34 using ::android::vintf::VintfObject;
35 
36 class KernelConfigVerifier final {
37   public:
KernelConfigVerifier()38     KernelConfigVerifier() : mRuntimeInfo(VintfObject::GetRuntimeInfo()) {}
39 
hasOption(const std::string & option) const40     bool hasOption(const std::string& option) const {
41         const auto& configMap = mRuntimeInfo->kernelConfigs();
42         auto it = configMap.find(option);
43         if (it != configMap.cend()) {
44             return it->second == "y";
45         }
46         return false;
47     }
48 
hasModule(const std::string & option) const49     bool hasModule(const std::string& option) const {
50         const auto& configMap = mRuntimeInfo->kernelConfigs();
51         auto it = configMap.find(option);
52         if (it != configMap.cend()) {
53             return (it->second == "y") || (it->second == "m");
54         }
55         return false;
56     }
57 
58   private:
59     std::shared_ptr<const RuntimeInfo> mRuntimeInfo;
60 };
61 
62 }  // namespace
63 
64 /**
65  * If this test fails, enable the following kernel modules in your kernel config:
66  * CONFIG_NET_CLS_MATCHALL=y
67  * CONFIG_NET_ACT_POLICE=y
68  * CONFIG_NET_ACT_BPF=y
69  * CONFIG_BPF_JIT=y
70  */
TEST(KernelTest,TestRateLimitingSupport)71 TEST(KernelTest, TestRateLimitingSupport) {
72     KernelConfigVerifier configVerifier;
73     EXPECT_TRUE(configVerifier.hasOption("CONFIG_NET_CLS_MATCHALL"));
74     EXPECT_TRUE(configVerifier.hasOption("CONFIG_NET_ACT_POLICE"));
75     EXPECT_TRUE(configVerifier.hasOption("CONFIG_NET_ACT_BPF"));
76     EXPECT_TRUE(configVerifier.hasOption("CONFIG_BPF_JIT"));
77 }
78 
TEST(KernelTest,TestRequireBpfUnprivDefaultOn)79 TEST(KernelTest, TestRequireBpfUnprivDefaultOn) {
80     KernelConfigVerifier configVerifier;
81     EXPECT_FALSE(configVerifier.hasOption("CONFIG_BPF_UNPRIV_DEFAULT_OFF"));
82 }
83 
TEST(KernelTest,TestBpfJitAlwaysOn)84 TEST(KernelTest, TestBpfJitAlwaysOn) {
85     if (bpf::isKernel32Bit() && !bpf::isAtLeastKernelVersion(5, 16, 0))
86         GTEST_SKIP() << "Exempt on obsolete 32-bit kernels.";
87     KernelConfigVerifier configVerifier;
88     ASSERT_TRUE(configVerifier.hasOption("CONFIG_BPF_JIT_ALWAYS_ON"));
89 }
90 
TEST(KernelTest,TestHaveEfficientUnalignedAccess)91 TEST(KernelTest, TestHaveEfficientUnalignedAccess) {
92     // Turns out the bpf verifier is stricter if you don't have this option.
93     // At least *some* of our bpf code fails to verify without it.
94     KernelConfigVerifier configVerifier;
95     ASSERT_TRUE(configVerifier.hasOption("CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS"));
96 }
97 
98 /* Android 14/U should only launch on 64-bit kernels
99  *   T launches on 5.10/5.15
100  *   U launches on 5.15/6.1
101  * So >=5.16 implies isKernel64Bit()
102  */
TEST(KernelTest,TestKernel64Bit)103 TEST(KernelTest, TestKernel64Bit) {
104     if (!bpf::isAtLeastKernelVersion(5, 16, 0)) GTEST_SKIP() << "Exempt on < 5.16 kernel.";
105     ASSERT_TRUE(bpf::isKernel64Bit());
106 }
107 
108 // Android V requires x86 kernels to be 64-bit, as among other things
109 // 32-bit x86 kernels have subtly different structure layouts for XFRM
TEST(KernelTest,TestX86Kernel64Bit)110 TEST(KernelTest, TestX86Kernel64Bit) {
111     if (!bpf::isX86()) GTEST_SKIP() << "Exempt on non-x86 architecture.";
112     ASSERT_TRUE(bpf::isKernel64Bit());
113 }
114 
115 // Android W requires 64-bit userspace on new 6.7+ kernels.
TEST(KernelTest,TestUser64Bit)116 TEST(KernelTest, TestUser64Bit) {
117     if (!bpf::isAtLeastKernelVersion(6, 7, 0)) GTEST_SKIP() << "Exempt on < 6.7 kernel.";
118     ASSERT_TRUE(bpf::isUserspace64bit());
119 }
120 
121 // Android V requires 4.19+
TEST(KernelTest,TestKernel419)122 TEST(KernelTest, TestKernel419) {
123     ASSERT_TRUE(bpf::isAtLeastKernelVersion(4, 19, 0));
124 }
125 
126 // Android W requires 5.4+
TEST(KernelTest,TestKernel54)127 TEST(KernelTest, TestKernel54) {
128     ASSERT_TRUE(bpf::isAtLeastKernelVersion(5, 4, 0));
129 }
130 
131 // RiscV is not yet supported: make it fail VTS.
TEST(KernelTest,TestNotRiscV)132 TEST(KernelTest, TestNotRiscV) {
133     ASSERT_TRUE(!bpf::isRiscV());
134 }
135 
TEST(KernelTest,TestIsLTS)136 TEST(KernelTest, TestIsLTS) {
137     ASSERT_TRUE(bpf::isLtsKernel());
138 }
139 
exists(const char * filename)140 static bool exists(const char* filename) {
141     return !access(filename, F_OK);
142 }
143 
isGSI()144 static bool isGSI() {
145     // From //system/gsid/libgsi.cpp IsGsiRunning()
146     return exists("/metadata/gsi/dsu/booted");
147 }
148 
149 #define ifIsKernelThenMinLTS(major, minor, sub) do { \
150     if (isGSI()) GTEST_SKIP() << "Test is meaningless on GSI."; \
151     if (!bpf::isKernelVersion((major), (minor))) GTEST_SKIP() << "Not for this LTS ver."; \
152     ASSERT_TRUE(bpf::isAtLeastKernelVersion((major), (minor), (sub))); \
153 } while (0)
154 
TEST(KernelTest,TestMinRequiredLTS_4_19)155 TEST(KernelTest, TestMinRequiredLTS_4_19) { ifIsKernelThenMinLTS(4, 19, 236); }
TEST(KernelTest,TestMinRequiredLTS_5_4)156 TEST(KernelTest, TestMinRequiredLTS_5_4)  { ifIsKernelThenMinLTS(5, 4, 186); }
TEST(KernelTest,TestMinRequiredLTS_5_10)157 TEST(KernelTest, TestMinRequiredLTS_5_10) { ifIsKernelThenMinLTS(5, 10, 199); }
TEST(KernelTest,TestMinRequiredLTS_5_15)158 TEST(KernelTest, TestMinRequiredLTS_5_15) { ifIsKernelThenMinLTS(5, 15, 136); }
TEST(KernelTest,TestMinRequiredLTS_6_1)159 TEST(KernelTest, TestMinRequiredLTS_6_1)  { ifIsKernelThenMinLTS(6, 1, 57); }
TEST(KernelTest,TestMinRequiredLTS_6_6)160 TEST(KernelTest, TestMinRequiredLTS_6_6)  { ifIsKernelThenMinLTS(6, 6, 0); }
TEST(KernelTest,TestMinRequiredLTS_6_12)161 TEST(KernelTest, TestMinRequiredLTS_6_12) { ifIsKernelThenMinLTS(6, 12, 0); }
162 
TEST(KernelTest,TestSupportsAcceptRaMinLft)163 TEST(KernelTest, TestSupportsAcceptRaMinLft) {
164     if (isGSI()) GTEST_SKIP() << "Meaningless on GSI due to ancient kernels.";
165     if (!bpf::isAtLeastKernelVersion(5, 10, 0)) GTEST_SKIP() << "Too old base kernel.";
166     ASSERT_TRUE(exists("/proc/sys/net/ipv6/conf/default/accept_ra_min_lft"));
167 }
168 
TEST(KernelTest,TestSupportsCommonUsbEthernetDongles)169 TEST(KernelTest, TestSupportsCommonUsbEthernetDongles) {
170     KernelConfigVerifier configVerifier;
171     if (!configVerifier.hasModule("CONFIG_USB")) GTEST_SKIP() << "Exempt without USB support.";
172     EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_AX8817X"));
173     EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_AX88179_178A"));
174     EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_CDCETHER"));
175     EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_CDC_EEM"));
176     EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_CDC_NCM"));
177     if (bpf::isAtLeastKernelVersion(5, 4, 0))
178         EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_AQC111"));
179 
180     EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_RTL8152"));
181     EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_RTL8150"));
182     if (bpf::isAtLeastKernelVersion(5, 15, 0)) {
183         EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_RTL8153_ECM"));
184         EXPECT_TRUE(configVerifier.hasModule("CONFIG_AX88796B_PHY"));
185     }
186 }
187 
188 }  // namespace net
189 }  // namespace android
190