| Patrick Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 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 | |
| Maciej Żenczykowski | 9da72b0 | 2024-06-06 22:00:15 +0000 | [diff] [blame] | 18 | #include <unistd.h> |
| 19 | |
| Patrick Rohr | 5aec118 | 2024-06-26 10:58:33 -0700 | [diff] [blame] | 20 | #include <android-base/properties.h> |
| Patrick Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 21 | #include <gtest/gtest.h> |
| 22 | #include <vintf/VintfObject.h> |
| 23 | |
| 24 | #include <fstream> |
| 25 | #include <string> |
| Patrick Rohr | 5aec118 | 2024-06-26 10:58:33 -0700 | [diff] [blame] | 26 | #include <unordered_set> |
| Patrick Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 27 | |
| Maciej Żenczykowski | 099e196 | 2023-05-04 11:16:26 +0000 | [diff] [blame] | 28 | #include "bpf/KernelUtils.h" |
| 29 | |
| Patrick Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 30 | namespace android { |
| 31 | namespace net { |
| 32 | |
| 33 | namespace { |
| 34 | |
| Patrick Rohr | 5aec118 | 2024-06-26 10:58:33 -0700 | [diff] [blame] | 35 | using ::android::base::GetProperty; |
| Patrick Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 36 | using ::android::vintf::RuntimeInfo; |
| 37 | using ::android::vintf::VintfObject; |
| 38 | |
| 39 | class KernelConfigVerifier final { |
| 40 | public: |
| Patrick Rohr | 5aec118 | 2024-06-26 10:58:33 -0700 | [diff] [blame] | 41 | 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 Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 55 | |
| 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 Żenczykowski | 7cfbac5 | 2023-10-12 19:52:36 +0000 | [diff] [blame] | 65 | 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 Rohr | 5aec118 | 2024-06-26 10:58:33 -0700 | [diff] [blame] | 74 | bool isAvailable(const std::string& option, const std::string& koName) const { |
| 75 | return hasOption(option) || mLoadedModules.contains(koName); |
| 76 | } |
| 77 | |
| Patrick Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 78 | private: |
| 79 | std::shared_ptr<const RuntimeInfo> mRuntimeInfo; |
| Patrick Rohr | 5aec118 | 2024-06-26 10:58:33 -0700 | [diff] [blame] | 80 | std::unordered_set<std::string> mLoadedModules; |
| Patrick Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 81 | }; |
| 82 | |
| Patrick Rohr | 382e0cd | 2025-02-26 18:12:25 -0800 | [diff] [blame] | 83 | bool isCuttlefish() { |
| 84 | return GetProperty("ro.product.board", "") == "cutf"; |
| 85 | } |
| 86 | |
| Patrick Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 87 | } // 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 Żenczykowski | b5f98e6 | 2022-12-16 20:29:31 +0000 | [diff] [blame] | 94 | * CONFIG_BPF_JIT=y |
| Patrick Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 95 | */ |
| 96 | TEST(KernelTest, TestRateLimitingSupport) { |
| Patrick Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 97 | KernelConfigVerifier configVerifier; |
| Maciej Żenczykowski | 8f14e5b | 2023-10-17 15:45:28 +0000 | [diff] [blame] | 98 | 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 Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 102 | } |
| 103 | |
| Maciej Żenczykowski | 40722a7 | 2024-03-15 08:08:59 +0000 | [diff] [blame] | 104 | TEST(KernelTest, TestRequireBpfUnprivDefaultOn) { |
| 105 | KernelConfigVerifier configVerifier; |
| 106 | EXPECT_FALSE(configVerifier.hasOption("CONFIG_BPF_UNPRIV_DEFAULT_OFF")); |
| 107 | } |
| 108 | |
| Maciej Żenczykowski | 099e196 | 2023-05-04 11:16:26 +0000 | [diff] [blame] | 109 | TEST(KernelTest, TestBpfJitAlwaysOn) { |
| Maciej Żenczykowski | 099e196 | 2023-05-04 11:16:26 +0000 | [diff] [blame] | 110 | KernelConfigVerifier configVerifier; |
| 111 | ASSERT_TRUE(configVerifier.hasOption("CONFIG_BPF_JIT_ALWAYS_ON")); |
| 112 | } |
| 113 | |
| Maciej Żenczykowski | 997e3b3 | 2024-08-22 21:08:58 +0000 | [diff] [blame] | 114 | TEST(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 Żenczykowski | 099e196 | 2023-05-04 11:16:26 +0000 | [diff] [blame] | 121 | /* 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 | */ |
| 126 | TEST(KernelTest, TestKernel64Bit) { |
| 127 | if (!bpf::isAtLeastKernelVersion(5, 16, 0)) GTEST_SKIP() << "Exempt on < 5.16 kernel."; |
| 128 | ASSERT_TRUE(bpf::isKernel64Bit()); |
| 129 | } |
| 130 | |
| Maciej Żenczykowski | b75cc34 | 2024-02-17 00:04:27 +0000 | [diff] [blame] | 131 | // 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 |
| 133 | TEST(KernelTest, TestX86Kernel64Bit) { |
| 134 | if (!bpf::isX86()) GTEST_SKIP() << "Exempt on non-x86 architecture."; |
| 135 | ASSERT_TRUE(bpf::isKernel64Bit()); |
| 136 | } |
| 137 | |
| Maciej Żenczykowski | f3316d7 | 2025-01-15 10:40:29 -0800 | [diff] [blame] | 138 | // Android 25Q2 requires 64-bit userspace on new 6.7+ kernels. |
| Maciej Żenczykowski | 89ae7b0 | 2025-02-20 23:35:15 -0800 | [diff] [blame] | 139 | TEST(KernelTest, DISABLED_TestUser64Bit) { |
| Maciej Żenczykowski | 01a1e47 | 2024-10-28 20:00:53 +0000 | [diff] [blame] | 140 | if (!bpf::isAtLeastKernelVersion(6, 7, 0)) GTEST_SKIP() << "Exempt on < 6.7 kernel."; |
| 141 | ASSERT_TRUE(bpf::isUserspace64bit()); |
| 142 | } |
| 143 | |
| Maciej Żenczykowski | f3316d7 | 2025-01-15 10:40:29 -0800 | [diff] [blame] | 144 | // Android 25Q2 requires 5.4+ |
| Maciej Żenczykowski | 462b439 | 2024-09-27 02:45:47 +0000 | [diff] [blame] | 145 | TEST(KernelTest, TestKernel54) { |
| 146 | ASSERT_TRUE(bpf::isAtLeastKernelVersion(5, 4, 0)); |
| 147 | } |
| 148 | |
| Maciej Żenczykowski | 36cba15 | 2024-05-15 11:50:17 +0000 | [diff] [blame] | 149 | // RiscV is not yet supported: make it fail VTS. |
| 150 | TEST(KernelTest, TestNotRiscV) { |
| 151 | ASSERT_TRUE(!bpf::isRiscV()); |
| 152 | } |
| 153 | |
| Maciej Żenczykowski | 653bbf0 | 2024-02-28 20:32:21 +0000 | [diff] [blame] | 154 | TEST(KernelTest, TestIsLTS) { |
| Maciej Żenczykowski | ddf2f2c | 2024-04-25 14:30:22 -0700 | [diff] [blame] | 155 | ASSERT_TRUE(bpf::isLtsKernel()); |
| Maciej Żenczykowski | 653bbf0 | 2024-02-28 20:32:21 +0000 | [diff] [blame] | 156 | } |
| 157 | |
| Maciej Żenczykowski | 9da72b0 | 2024-06-06 22:00:15 +0000 | [diff] [blame] | 158 | static bool exists(const char* filename) { |
| 159 | return !access(filename, F_OK); |
| 160 | } |
| 161 | |
| Maciej Żenczykowski | 7e61274 | 2024-03-27 14:06:42 -0700 | [diff] [blame] | 162 | static bool isGSI() { |
| 163 | // From //system/gsid/libgsi.cpp IsGsiRunning() |
| Maciej Żenczykowski | 9da72b0 | 2024-06-06 22:00:15 +0000 | [diff] [blame] | 164 | return exists("/metadata/gsi/dsu/booted"); |
| Maciej Żenczykowski | 7e61274 | 2024-03-27 14:06:42 -0700 | [diff] [blame] | 165 | } |
| 166 | |
| Maciej Żenczykowski | 07d1389 | 2024-03-01 20:47:07 -0800 | [diff] [blame] | 167 | #define ifIsKernelThenMinLTS(major, minor, sub) do { \ |
| Maciej Żenczykowski | 7e61274 | 2024-03-27 14:06:42 -0700 | [diff] [blame] | 168 | if (isGSI()) GTEST_SKIP() << "Test is meaningless on GSI."; \ |
| Maciej Żenczykowski | ddf2f2c | 2024-04-25 14:30:22 -0700 | [diff] [blame] | 169 | if (!bpf::isKernelVersion((major), (minor))) GTEST_SKIP() << "Not for this LTS ver."; \ |
| Maciej Żenczykowski | 7e61274 | 2024-03-27 14:06:42 -0700 | [diff] [blame] | 170 | ASSERT_TRUE(bpf::isAtLeastKernelVersion((major), (minor), (sub))); \ |
| Maciej Żenczykowski | 07d1389 | 2024-03-01 20:47:07 -0800 | [diff] [blame] | 171 | } while (0) |
| Maciej Żenczykowski | 653bbf0 | 2024-02-28 20:32:21 +0000 | [diff] [blame] | 172 | |
| Maciej Żenczykowski | 7004c06 | 2025-01-15 10:43:53 -0800 | [diff] [blame] | 173 | TEST(KernelTest, TestMinRequiredLTS_5_4) { ifIsKernelThenMinLTS(5, 4, 277); } |
| 174 | TEST(KernelTest, TestMinRequiredLTS_5_10) { ifIsKernelThenMinLTS(5, 10, 210); } |
| 175 | TEST(KernelTest, TestMinRequiredLTS_5_15) { ifIsKernelThenMinLTS(5, 15, 149); } |
| 176 | TEST(KernelTest, TestMinRequiredLTS_6_1) { ifIsKernelThenMinLTS(6, 1, 78); } |
| 177 | TEST(KernelTest, TestMinRequiredLTS_6_6) { ifIsKernelThenMinLTS(6, 6, 30); } |
| Maciej Żenczykowski | 82c3201 | 2025-02-17 10:32:29 -0800 | [diff] [blame] | 178 | TEST(KernelTest, TestMinRequiredLTS_6_12) { ifIsKernelThenMinLTS(6, 12, 13); } |
| Maciej Żenczykowski | 653bbf0 | 2024-02-28 20:32:21 +0000 | [diff] [blame] | 179 | |
| Maciej Żenczykowski | 9da72b0 | 2024-06-06 22:00:15 +0000 | [diff] [blame] | 180 | TEST(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 Żenczykowski | 5952cee | 2025-03-03 16:29:55 -0800 | [diff] [blame] | 186 | TEST(KernelTest, TestSupportsBpfLsm) { |
| 187 | if (isGSI()) GTEST_SKIP() << "Meaningless on GSI due to ancient kernels."; |
| Maciej Żenczykowski | 04aa0d7 | 2025-03-04 11:50:13 -0800 | [diff] [blame^] | 188 | if (!bpf::isAtLeastKernelVersion(6, 2, 0)) GTEST_SKIP() << "Too old base kernel."; |
| Maciej Żenczykowski | 5952cee | 2025-03-03 16:29:55 -0800 | [diff] [blame] | 189 | KernelConfigVerifier configVerifier; |
| 190 | ASSERT_TRUE(configVerifier.hasOption("CONFIG_BPF_LSM")); |
| 191 | } |
| 192 | |
| Maciej Żenczykowski | 7cfbac5 | 2023-10-12 19:52:36 +0000 | [diff] [blame] | 193 | TEST(KernelTest, TestSupportsCommonUsbEthernetDongles) { |
| 194 | KernelConfigVerifier configVerifier; |
| 195 | if (!configVerifier.hasModule("CONFIG_USB")) GTEST_SKIP() << "Exempt without USB support."; |
| Maciej Żenczykowski | 8f14e5b | 2023-10-17 15:45:28 +0000 | [diff] [blame] | 196 | 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 Żenczykowski | 99dc5da | 2023-10-12 23:22:02 +0000 | [diff] [blame] | 201 | if (bpf::isAtLeastKernelVersion(5, 4, 0)) |
| Maciej Żenczykowski | 8f14e5b | 2023-10-17 15:45:28 +0000 | [diff] [blame] | 202 | EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_NET_AQC111")); |
| Maciej Żenczykowski | 99dc5da | 2023-10-12 23:22:02 +0000 | [diff] [blame] | 203 | |
| Maciej Żenczykowski | 8f14e5b | 2023-10-17 15:45:28 +0000 | [diff] [blame] | 204 | EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_RTL8152")); |
| 205 | EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_RTL8150")); |
| Maciej Żenczykowski | 72a8386 | 2023-10-16 18:18:56 +0000 | [diff] [blame] | 206 | if (bpf::isAtLeastKernelVersion(5, 15, 0)) { |
| Maciej Żenczykowski | 8f14e5b | 2023-10-17 15:45:28 +0000 | [diff] [blame] | 207 | EXPECT_TRUE(configVerifier.hasModule("CONFIG_USB_RTL8153_ECM")); |
| 208 | EXPECT_TRUE(configVerifier.hasModule("CONFIG_AX88796B_PHY")); |
| Maciej Żenczykowski | 72a8386 | 2023-10-16 18:18:56 +0000 | [diff] [blame] | 209 | } |
| Maciej Żenczykowski | 7cfbac5 | 2023-10-12 19:52:36 +0000 | [diff] [blame] | 210 | } |
| 211 | |
| Patrick Rohr | 382e0cd | 2025-02-26 18:12:25 -0800 | [diff] [blame] | 212 | /** |
| 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) |
| 217 | TEST(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 Rohr | f01ea79 | 2025-02-27 09:59:24 -0800 | [diff] [blame] | 227 | // TODO: check for hasSystemFeature(FEATURE_USB_ACCESSORY) |
| 228 | TEST(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 Rohr | bdafd74 | 2022-02-23 19:29:52 +0100 | [diff] [blame] | 234 | } // namespace net |
| 235 | } // namespace android |