blob: fbee8c66fd14cbdb37d4d52a298525022794da59 [file] [log] [blame]
Patrick Rohrbdafd742022-02-23 19:29:52 +01001/*
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
Maciej Żenczykowski9da72b02024-06-06 22:00:15 +000018#include <unistd.h>
19
Patrick Rohr5aec1182024-06-26 10:58:33 -070020#include <android-base/properties.h>
Patrick Rohrbdafd742022-02-23 19:29:52 +010021#include <gtest/gtest.h>
22#include <vintf/VintfObject.h>
23
24#include <fstream>
25#include <string>
Patrick Rohr5aec1182024-06-26 10:58:33 -070026#include <unordered_set>
Patrick Rohrbdafd742022-02-23 19:29:52 +010027
Maciej Żenczykowski099e1962023-05-04 11:16:26 +000028#include "bpf/KernelUtils.h"
29
Patrick Rohrbdafd742022-02-23 19:29:52 +010030namespace android {
31namespace net {
32
33namespace {
34
Patrick Rohr5aec1182024-06-26 10:58:33 -070035using ::android::base::GetProperty;
Patrick Rohrbdafd742022-02-23 19:29:52 +010036using ::android::vintf::RuntimeInfo;
37using ::android::vintf::VintfObject;
38
39class KernelConfigVerifier final {
40 public:
Patrick Rohr5aec1182024-06-26 10:58:33 -070041 KernelConfigVerifier() : mRuntimeInfo(VintfObject::GetRuntimeInfo()) {
42 std::ifstream procModules("/proc/modules", std::ios::in);
43 if (!procModules) {
44 // Return early, this will likely cause the test to fail. However, gtest FAIL() cannot
45 // be used outside of an actual test method.
46 return;
47 }
48 std::string modline;
49 while (std::getline(procModules, modline)) {
50 // modline contains a single line read from /proc/modules. For example:
51 // virtio_snd 45056 0 - Live 0x0000000000000000 (E)
52 mLoadedModules.emplace(modline.substr(0, modline.find(' ')));
53 }
54 }
Patrick Rohrbdafd742022-02-23 19:29:52 +010055
56 bool hasOption(const std::string& option) const {
57 const auto& configMap = mRuntimeInfo->kernelConfigs();
58 auto it = configMap.find(option);
59 if (it != configMap.cend()) {
60 return it->second == "y";
61 }
62 return false;
63 }
64
Maciej Żenczykowski7cfbac52023-10-12 19:52:36 +000065 bool hasModule(const std::string& option) const {
66 const auto& configMap = mRuntimeInfo->kernelConfigs();
67 auto it = configMap.find(option);
68 if (it != configMap.cend()) {
69 return (it->second == "y") || (it->second == "m");
70 }
71 return false;
72 }
73
Patrick Rohr5aec1182024-06-26 10:58:33 -070074 bool isAvailable(const std::string& option, const std::string& koName) const {
75 return hasOption(option) || mLoadedModules.contains(koName);
76 }
77
Patrick Rohrbdafd742022-02-23 19:29:52 +010078 private:
79 std::shared_ptr<const RuntimeInfo> mRuntimeInfo;
Patrick Rohr5aec1182024-06-26 10:58:33 -070080 std::unordered_set<std::string> mLoadedModules;
Patrick Rohrbdafd742022-02-23 19:29:52 +010081};
82
Patrick Rohr382e0cd2025-02-26 18:12:25 -080083bool isCuttlefish() {
84 return GetProperty("ro.product.board", "") == "cutf";
85}
86
Patrick Rohrbdafd742022-02-23 19:29:52 +010087} // namespace
88
89/**
90 * If this test fails, enable the following kernel modules in your kernel config:
91 * CONFIG_NET_CLS_MATCHALL=y
92 * CONFIG_NET_ACT_POLICE=y
93 * CONFIG_NET_ACT_BPF=y
Maciej Żenczykowskib5f98e62022-12-16 20:29:31 +000094 * CONFIG_BPF_JIT=y
Patrick Rohrbdafd742022-02-23 19:29:52 +010095 */
96TEST(KernelTest, TestRateLimitingSupport) {
Patrick Rohrbdafd742022-02-23 19:29:52 +010097 KernelConfigVerifier configVerifier;
Maciej Żenczykowski8f14e5b2023-10-17 15:45:28 +000098 EXPECT_TRUE(configVerifier.hasOption("CONFIG_NET_CLS_MATCHALL"));
99 EXPECT_TRUE(configVerifier.hasOption("CONFIG_NET_ACT_POLICE"));
100 EXPECT_TRUE(configVerifier.hasOption("CONFIG_NET_ACT_BPF"));
101 EXPECT_TRUE(configVerifier.hasOption("CONFIG_BPF_JIT"));
Patrick Rohrbdafd742022-02-23 19:29:52 +0100102}
103
Maciej Żenczykowski40722a72024-03-15 08:08:59 +0000104TEST(KernelTest, TestRequireBpfUnprivDefaultOn) {
105 KernelConfigVerifier configVerifier;
106 EXPECT_FALSE(configVerifier.hasOption("CONFIG_BPF_UNPRIV_DEFAULT_OFF"));
107}
108
Maciej Żenczykowski099e1962023-05-04 11:16:26 +0000109TEST(KernelTest, TestBpfJitAlwaysOn) {
Maciej Żenczykowski099e1962023-05-04 11:16:26 +0000110 KernelConfigVerifier configVerifier;
111 ASSERT_TRUE(configVerifier.hasOption("CONFIG_BPF_JIT_ALWAYS_ON"));
112}
113
Maciej Żenczykowski997e3b32024-08-22 21:08:58 +0000114TEST(KernelTest, TestHaveEfficientUnalignedAccess) {
115 // Turns out the bpf verifier is stricter if you don't have this option.
116 // At least *some* of our bpf code fails to verify without it.
117 KernelConfigVerifier configVerifier;
118 ASSERT_TRUE(configVerifier.hasOption("CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS"));
119}
120
Maciej Żenczykowski099e1962023-05-04 11:16:26 +0000121/* Android 14/U should only launch on 64-bit kernels
122 * T launches on 5.10/5.15
123 * U launches on 5.15/6.1
124 * So >=5.16 implies isKernel64Bit()
125 */
126TEST(KernelTest, TestKernel64Bit) {
127 if (!bpf::isAtLeastKernelVersion(5, 16, 0)) GTEST_SKIP() << "Exempt on < 5.16 kernel.";
128 ASSERT_TRUE(bpf::isKernel64Bit());
129}
130
Maciej Żenczykowskib75cc342024-02-17 00:04:27 +0000131// Android V requires x86 kernels to be 64-bit, as among other things
132// 32-bit x86 kernels have subtly different structure layouts for XFRM
133TEST(KernelTest, TestX86Kernel64Bit) {
134 if (!bpf::isX86()) GTEST_SKIP() << "Exempt on non-x86 architecture.";
135 ASSERT_TRUE(bpf::isKernel64Bit());
136}
137
Maciej Żenczykowskif3316d72025-01-15 10:40:29 -0800138// Android 25Q2 requires 64-bit userspace on new 6.7+ kernels.
Maciej Żenczykowski89ae7b02025-02-20 23:35:15 -0800139TEST(KernelTest, DISABLED_TestUser64Bit) {
Maciej Żenczykowski01a1e472024-10-28 20:00:53 +0000140 if (!bpf::isAtLeastKernelVersion(6, 7, 0)) GTEST_SKIP() << "Exempt on < 6.7 kernel.";
141 ASSERT_TRUE(bpf::isUserspace64bit());
142}
143
Maciej Żenczykowskif3316d72025-01-15 10:40:29 -0800144// Android 25Q2 requires 5.4+
Maciej Żenczykowski462b4392024-09-27 02:45:47 +0000145TEST(KernelTest, TestKernel54) {
146 ASSERT_TRUE(bpf::isAtLeastKernelVersion(5, 4, 0));
147}
148
Maciej Żenczykowski36cba152024-05-15 11:50:17 +0000149// RiscV is not yet supported: make it fail VTS.
150TEST(KernelTest, TestNotRiscV) {
151 ASSERT_TRUE(!bpf::isRiscV());
152}
153
Maciej Żenczykowski653bbf02024-02-28 20:32:21 +0000154TEST(KernelTest, TestIsLTS) {
Maciej Żenczykowskiddf2f2c2024-04-25 14:30:22 -0700155 ASSERT_TRUE(bpf::isLtsKernel());
Maciej Żenczykowski653bbf02024-02-28 20:32:21 +0000156}
157
Maciej Żenczykowski9da72b02024-06-06 22:00:15 +0000158static bool exists(const char* filename) {
159 return !access(filename, F_OK);
160}
161
Maciej Żenczykowski7e612742024-03-27 14:06:42 -0700162static bool isGSI() {
163 // From //system/gsid/libgsi.cpp IsGsiRunning()
Maciej Żenczykowski9da72b02024-06-06 22:00:15 +0000164 return exists("/metadata/gsi/dsu/booted");
Maciej Żenczykowski7e612742024-03-27 14:06:42 -0700165}
166
Maciej Żenczykowski07d13892024-03-01 20:47:07 -0800167#define ifIsKernelThenMinLTS(major, minor, sub) do { \
Maciej Żenczykowski7e612742024-03-27 14:06:42 -0700168 if (isGSI()) GTEST_SKIP() << "Test is meaningless on GSI."; \
Maciej Żenczykowskiddf2f2c2024-04-25 14:30:22 -0700169 if (!bpf::isKernelVersion((major), (minor))) GTEST_SKIP() << "Not for this LTS ver."; \
Maciej Żenczykowski7e612742024-03-27 14:06:42 -0700170 ASSERT_TRUE(bpf::isAtLeastKernelVersion((major), (minor), (sub))); \
Maciej Żenczykowski07d13892024-03-01 20:47:07 -0800171} while (0)
Maciej Żenczykowski653bbf02024-02-28 20:32:21 +0000172
Maciej Żenczykowski7004c062025-01-15 10:43:53 -0800173TEST(KernelTest, TestMinRequiredLTS_5_4) { ifIsKernelThenMinLTS(5, 4, 277); }
174TEST(KernelTest, TestMinRequiredLTS_5_10) { ifIsKernelThenMinLTS(5, 10, 210); }
175TEST(KernelTest, TestMinRequiredLTS_5_15) { ifIsKernelThenMinLTS(5, 15, 149); }
176TEST(KernelTest, TestMinRequiredLTS_6_1) { ifIsKernelThenMinLTS(6, 1, 78); }
177TEST(KernelTest, TestMinRequiredLTS_6_6) { ifIsKernelThenMinLTS(6, 6, 30); }
Maciej Żenczykowski82c32012025-02-17 10:32:29 -0800178TEST(KernelTest, TestMinRequiredLTS_6_12) { ifIsKernelThenMinLTS(6, 12, 13); }
Maciej Żenczykowski653bbf02024-02-28 20:32:21 +0000179
Maciej Żenczykowski9da72b02024-06-06 22:00:15 +0000180TEST(KernelTest, TestSupportsAcceptRaMinLft) {
181 if (isGSI()) GTEST_SKIP() << "Meaningless on GSI due to ancient kernels.";
182 if (!bpf::isAtLeastKernelVersion(5, 10, 0)) GTEST_SKIP() << "Too old base kernel.";
183 ASSERT_TRUE(exists("/proc/sys/net/ipv6/conf/default/accept_ra_min_lft"));
184}
185
Maciej Żenczykowski5952cee2025-03-03 16:29:55 -0800186TEST(KernelTest, TestSupportsBpfLsm) {
187 if (isGSI()) GTEST_SKIP() << "Meaningless on GSI due to ancient kernels.";
Maciej Żenczykowski04aa0d72025-03-04 11:50:13 -0800188 if (!bpf::isAtLeastKernelVersion(6, 2, 0)) GTEST_SKIP() << "Too old base kernel.";
Maciej Żenczykowski5952cee2025-03-03 16:29:55 -0800189 KernelConfigVerifier configVerifier;
190 ASSERT_TRUE(configVerifier.hasOption("CONFIG_BPF_LSM"));
191}
192
Maciej Żenczykowski7cfbac52023-10-12 19:52:36 +0000193TEST(KernelTest, TestSupportsCommonUsbEthernetDongles) {
194 KernelConfigVerifier configVerifier;
195 if (!configVerifier.hasModule("CONFIG_USB")) GTEST_SKIP() << "Exempt without USB support.";
Maciej Żenczykowski8f14e5b2023-10-17 15:45:28 +0000196 EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_AX8817X"));
197 EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_AX88179_178A"));
198 EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_CDCETHER"));
199 EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_CDC_EEM"));
200 EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_CDC_NCM"));
Maciej Żenczykowski99dc5da2023-10-12 23:22:02 +0000201 if (bpf::isAtLeastKernelVersion(5, 4, 0))
Maciej Żenczykowski8f14e5b2023-10-17 15:45:28 +0000202 EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_AQC111"));
Maciej Żenczykowski99dc5da2023-10-12 23:22:02 +0000203
Maciej Żenczykowski8f14e5b2023-10-17 15:45:28 +0000204 EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_RTL8152"));
205 EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_RTL8150"));
Maciej Żenczykowski72a83862023-10-16 18:18:56 +0000206 if (bpf::isAtLeastKernelVersion(5, 15, 0)) {
Maciej Żenczykowski8f14e5b2023-10-17 15:45:28 +0000207 EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_RTL8153_ECM"));
208 EXPECT_TRUE(configVerifier.hasModule("CONFIG_AX88796B_PHY"));
Maciej Żenczykowski72a83862023-10-16 18:18:56 +0000209 }
Maciej Żenczykowski7cfbac52023-10-12 19:52:36 +0000210}
211
Patrick Rohr382e0cd2025-02-26 18:12:25 -0800212/**
213 * In addition to TestSupportsCommonUsbEthernetDongles, ensure that USB CDC host drivers are either
214 * builtin or loaded on physical devices.
215 */
216// TODO: check for hasSystemFeature(FEATURE_USB_HOST)
217TEST(KernelTest, TestSupportsUsbCdcHost) {
218 KernelConfigVerifier configVerifier;
219 // TODO: Load these modules on cuttlefish.
220 if (isCuttlefish()) GTEST_SKIP() << "Exempt on cuttlefish";
221
222 EXPECT_TRUE(configVerifier.isAvailable("CONFIG_USB_NET_CDC_NCM", "cdc_ncm"));
223 EXPECT_TRUE(configVerifier.isAvailable("CONFIG_USB_NET_CDC_EEM", "cdc_eem"));
224 EXPECT_TRUE(configVerifier.isAvailable("CONFIG_USB_NET_CDCETHER", "cdc_ether"));
225}
226
Patrick Rohrf01ea792025-02-27 09:59:24 -0800227// TODO: check for hasSystemFeature(FEATURE_USB_ACCESSORY)
228TEST(KernelTest, TestSupportsUsbNcmGadget) {
229 KernelConfigVerifier configVerifier;
230 EXPECT_TRUE(configVerifier.isAvailable("CONFIG_USB_F_NCM", "usb_f_ncm"));
231 EXPECT_TRUE(configVerifier.hasOption("CONFIG_USB_CONFIGFS_NCM"));
232}
233
Patrick Rohrbdafd742022-02-23 19:29:52 +0100234} // namespace net
235} // namespace android