diff options
-rw-r--r-- | Android.bp | 11 | ||||
-rw-r--r-- | include/mainline/XtBpfProgLocations.h | 37 | ||||
-rw-r--r-- | server/Android.bp | 30 | ||||
-rw-r--r-- | server/BandwidthController.cpp | 7 | ||||
-rw-r--r-- | server/BandwidthControllerTest.cpp | 2 | ||||
-rw-r--r-- | server/Controllers.cpp | 10 | ||||
-rw-r--r-- | server/TcUtils.h | 52 | ||||
-rw-r--r-- | server/TetherController.h | 3 | ||||
-rw-r--r-- | tests/Android.bp | 12 | ||||
-rw-r--r-- | tests/benchmarks/Android.bp | 6 | ||||
-rw-r--r-- | tests/binder_test.cpp | 304 |
11 files changed, 93 insertions, 381 deletions
@@ -33,6 +33,17 @@ cc_library_headers { min_sdk_version: "29", } +cc_library_headers { + name: "netd_mainline_headers", + export_include_dirs: ["include/mainline"], + apex_available: [ + "//apex_available:platform", + "com.android.tethering", + ], + sdk_version: "29", + min_sdk_version: "29", +} + cc_defaults { name: "netd_defaults", cflags: [ diff --git a/include/mainline/XtBpfProgLocations.h b/include/mainline/XtBpfProgLocations.h new file mode 100644 index 00000000..95a5742c --- /dev/null +++ b/include/mainline/XtBpfProgLocations.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +/* -=-=-=-=-= WARNING -=-=-=-=-=- + * + * DO *NOT* *EVER* CHANGE THESE - they *MUST* match what the Tethering mainline module provides! + * + * You cannot even change them in sync, since newer module must work on older Android T releases. + * + * You could with difficulty, uprevs of the bpfloader, api detection logic in mainline, etc, + * change this in Android U or later, but even that is a very bad idea and not worth the hassle. + * + * + * Mainline Tethering module on T+ is expected to make available to netd (for use by + * BandwidthController iptables initialization code) four xt_bpf programs at the following + * locations: + */ +#define XT_BPF_NETD(NAME) "/sys/fs/bpf/netd_shared/prog_netd_skfilter_" NAME "_xtbpf" +#define XT_BPF_ALLOWLIST_PROG_PATH XT_BPF_NETD("allowlist") +#define XT_BPF_DENYLIST_PROG_PATH XT_BPF_NETD("denylist") +#define XT_BPF_EGRESS_PROG_PATH XT_BPF_NETD("egress") +#define XT_BPF_INGRESS_PROG_PATH XT_BPF_NETD("ingress") diff --git a/server/Android.bp b/server/Android.bp index f29f6cfc..06ea0bab 100644 --- a/server/Android.bp +++ b/server/Android.bp @@ -37,12 +37,15 @@ filegroup { // Modules common to both netd and netd_unit_test cc_library_static { name: "libnetd_server", - defaults: ["netd_defaults"], + defaults: [ + "netd_aidl_interface_lateststable_cpp_shared", + "netd_defaults", + ], include_dirs: [ "system/netd/include", "system/netd/server/binder", ], - header_libs: ["bpf_connectivity_headers"], + header_libs: ["bpf_headers"], srcs: [ "BandwidthController.cpp", "Controllers.cpp", @@ -71,7 +74,6 @@ cc_library_static { "libpcap", "libssl", "libsysutils", - "netd_aidl_interface-V8-cpp", "netd_event_listener_interface-V1-cpp", ], static_libs: [ @@ -86,7 +88,10 @@ cc_library_static { cc_binary { name: "netd", - defaults: ["netd_defaults"], + defaults: [ + "netd_aidl_interface_lateststable_cpp_shared", + "netd_defaults", + ], include_dirs: [ "external/mdnsresponder/mDNSShared", "system/netd/include", @@ -95,7 +100,7 @@ cc_binary { required: [ "bpfloader", ], - header_libs: ["bpf_connectivity_headers"], + header_libs: ["bpf_headers"], shared_libs: [ "android.system.net.netd@1.0", "android.system.net.netd@1.1", @@ -116,7 +121,6 @@ cc_binary { "libsysutils", "libutils", "mdns_aidl_interface-V1-cpp", - "netd_aidl_interface-V8-cpp", "netd_event_listener_interface-V1-cpp", "oemnetd_aidl_interface-cpp", ], @@ -156,7 +160,10 @@ cc_binary { cc_binary { name: "ndc", - defaults: ["netd_defaults"], + defaults: [ + "netd_aidl_interface_lateststable_cpp_shared", + "netd_defaults", + ], include_dirs: [ "system/netd/include", ], @@ -172,7 +179,6 @@ cc_binary { "libutils", "libbinder", "dnsresolver_aidl_interface-V7-cpp", - "netd_aidl_interface-V8-cpp", ], srcs: [ "ndc.cpp", @@ -187,7 +193,10 @@ cc_binary { cc_test { name: "netd_unit_test", - defaults: ["netd_defaults"], + defaults: [ + "netd_aidl_interface_lateststable_cpp_static", + "netd_defaults", + ], test_suites: ["device-tests"], require_root: true, include_dirs: [ @@ -195,7 +204,7 @@ cc_test { "system/netd/server/binder", "system/netd/tests", ], - header_libs: ["bpf_connectivity_headers"], + header_libs: ["bpf_headers"], tidy_timeout_srcs: [ "BandwidthControllerTest.cpp", "InterfaceControllerTest.cpp", @@ -223,7 +232,6 @@ cc_test { "libnetd_server", "libnetd_test_tun_interface", "libtcutils", - "netd_aidl_interface-V8-cpp", "netd_event_listener_interface-V1-cpp", ], shared_libs: [ diff --git a/server/BandwidthController.cpp b/server/BandwidthController.cpp index 96a82e23..8dba75a5 100644 --- a/server/BandwidthController.cpp +++ b/server/BandwidthController.cpp @@ -55,6 +55,7 @@ #include "FirewallController.h" /* For makeCriticalCommands */ #include "Fwmark.h" #include "NetdConstants.h" +#include "android/net/INetd.h" #include "bpf/BpfUtils.h" /* Alphabetical */ @@ -66,9 +67,6 @@ const char BandwidthController::LOCAL_RAW_PREROUTING[] = "bw_raw_PREROUTING"; const char BandwidthController::LOCAL_MANGLE_POSTROUTING[] = "bw_mangle_POSTROUTING"; const char BandwidthController::LOCAL_GLOBAL_ALERT[] = "bw_global_alert"; -// Sync from packages/modules/Connectivity/bpf_progs/clatd.c -#define CLAT_MARK 0xdeadc1a7 - auto BandwidthController::iptablesRestoreFunction = execIptablesRestoreWithOutput; using android::base::Join; @@ -76,6 +74,7 @@ using android::base::StartsWith; using android::base::StringAppendF; using android::base::StringPrintf; using android::net::FirewallController; +using android::net::INetd::CLAT_MARK; using android::netdutils::StatusOr; using android::netdutils::UniqueFile; @@ -147,8 +146,6 @@ const std::string NEW_CHAIN_COMMAND = "-N "; */ const std::string COMMIT_AND_CLOSE = "COMMIT\n"; -const std::string BPF_PENALTY_BOX_MATCH_DENYLIST_COMMAND = StringPrintf( - "-I bw_penalty_box -m bpf --object-pinned %s -j REJECT", XT_BPF_DENYLIST_PROG_PATH); static const std::vector<std::string> IPT_FLUSH_COMMANDS = { /* diff --git a/server/BandwidthControllerTest.cpp b/server/BandwidthControllerTest.cpp index e7d29d23..844681d0 100644 --- a/server/BandwidthControllerTest.cpp +++ b/server/BandwidthControllerTest.cpp @@ -34,7 +34,7 @@ #include "BandwidthController.h" #include "Fwmark.h" #include "IptablesBaseTest.h" -#include "bpf_shared.h" +#include "mainline/XtBpfProgLocations.h" #include "tun_interface.h" using ::testing::_; diff --git a/server/Controllers.cpp b/server/Controllers.cpp index 0df6b0ee..00ee186d 100644 --- a/server/Controllers.cpp +++ b/server/Controllers.cpp @@ -277,7 +277,15 @@ void Controllers::init() { initIptablesRules(); Stopwatch s; - bandwidthCtrl.enableBandwidthControl(); + if (int ret = bandwidthCtrl.enableBandwidthControl()) { + gLog.error("Failed to initialize BandwidthController (%s)", strerror(-ret)); + // A failure to init almost definitely means that iptables failed to load + // our static ruleset, which then basically means network accounting will not work. + // As such simply exit netd. This may crash loop the system, but by failing + // to bootup we will trigger rollback and thus this offers us protection against + // a mainline update breaking things. + exit(1); + } gLog.info("Enabling bandwidth control: %" PRId64 "us", s.getTimeAndResetUs()); if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) { diff --git a/server/TcUtils.h b/server/TcUtils.h index d205c04b..4b1b2b9f 100644 --- a/server/TcUtils.h +++ b/server/TcUtils.h @@ -26,42 +26,10 @@ #include <string> #include "bpf/BpfUtils.h" -#include "bpf_shared.h" namespace android { namespace net { -// For better code clarity - do not change values - used for booleans like -// with_ethernet_header or isEthernet. -constexpr bool RAWIP = false; -constexpr bool ETHER = true; - -// For better code clarity when used for 'bool ingress' parameter. -constexpr bool EGRESS = false; -constexpr bool INGRESS = true; - -// The priority of clat hook - must be after tethering. -constexpr uint16_t PRIO_CLAT = 4; - -inline base::Result<bool> isEthernet(const std::string& interface) { - bool result = false; - if (int error = ::android::isEthernet(interface.c_str(), result)) { - errno = error; - return ErrnoErrorf("isEthernet failed for interface {}", interface); - } - return result; -} - -inline int getClatEgress4MapFd(void) { - const int fd = bpf::mapRetrieveRW(CLAT_EGRESS4_MAP_PATH); - return (fd == -1) ? -errno : fd; -} - -inline int getClatIngress6MapFd(void) { - const int fd = bpf::mapRetrieveRW(CLAT_INGRESS6_MAP_PATH); - return (fd == -1) ? -errno : fd; -} - inline int tcQdiscAddDevClsact(int ifIndex) { return doTcQdiscClsact(ifIndex, RTM_NEWQDISC, NLM_F_EXCL | NLM_F_CREATE); } @@ -74,25 +42,5 @@ inline int tcQdiscDelDevClsact(int ifIndex) { return doTcQdiscClsact(ifIndex, RTM_DELQDISC, 0); } -// tc filter add dev .. ingress prio 4 protocol ipv6 bpf object-pinned /sys/fs/bpf/... direct-action -inline int tcFilterAddDevIngressClatIpv6(int ifIndex, const std::string& bpfProgPath) { - return tcAddBpfFilter(ifIndex, INGRESS, PRIO_CLAT, ETH_P_IPV6, bpfProgPath.c_str()); -} - -// tc filter add dev .. egress prio 4 protocol ip bpf object-pinned /sys/fs/bpf/... direct-action -inline int tcFilterAddDevEgressClatIpv4(int ifIndex, const std::string& bpfProgPath) { - return tcAddBpfFilter(ifIndex, EGRESS, PRIO_CLAT, ETH_P_IP, bpfProgPath.c_str()); -} - -// tc filter del dev .. ingress prio 4 protocol ipv6 -inline int tcFilterDelDevIngressClatIpv6(int ifIndex) { - return tcDeleteFilter(ifIndex, INGRESS, PRIO_CLAT, ETH_P_IPV6); -} - -// tc filter del dev .. egress prio 4 protocol ip -inline int tcFilterDelDevEgressClatIpv4(int ifIndex) { - return tcDeleteFilter(ifIndex, EGRESS, PRIO_CLAT, ETH_P_IP); -} - } // namespace net } // namespace android diff --git a/server/TetherController.h b/server/TetherController.h index b4472bd5..d2195f23 100644 --- a/server/TetherController.h +++ b/server/TetherController.h @@ -28,10 +28,11 @@ #include "NetdConstants.h" #include "android-base/result.h" #include "bpf/BpfMap.h" -#include "bpf_shared.h" #include "android/net/TetherOffloadRuleParcel.h" +#include "mainline/XtBpfProgLocations.h" + namespace android { namespace net { diff --git a/tests/Android.bp b/tests/Android.bp index 21830d6d..ff918cc1 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -37,7 +37,10 @@ cc_test_library { cc_test_library { name: "libnetd_test_unsol_service", - defaults: ["netd_defaults"], + defaults: [ + "netd_aidl_interface_lateststable_cpp_shared", + "netd_defaults", + ], srcs: [ "TestUnsolService.cpp" ], @@ -52,7 +55,6 @@ cc_test_library { "libnetutils", "libsysutils", "libutils", - "netd_aidl_interface-V8-cpp", ], } @@ -74,7 +76,10 @@ cc_test { "vts" ], require_root: true, - defaults: ["netd_defaults"], + defaults: [ + "netd_aidl_interface_lateststable_cpp_static", + "netd_defaults", + ], tidy: false, // cuts test build time by almost 1 minute srcs: [ ":netd_integration_test_shared", @@ -109,7 +114,6 @@ cc_test { "libnettestutils", "libtcutils", "mdns_aidl_interface-V1-cpp", - "netd_aidl_interface-V8-cpp", "netd_event_listener_interface-V1-cpp", "oemnetd_aidl_interface-cpp", ], diff --git a/tests/benchmarks/Android.bp b/tests/benchmarks/Android.bp index 95c00aa6..13c8105f 100644 --- a/tests/benchmarks/Android.bp +++ b/tests/benchmarks/Android.bp @@ -11,7 +11,10 @@ package { cc_benchmark { name: "netd_benchmark", - defaults: ["netd_defaults"], + defaults: [ + "netd_aidl_interface_lateststable_cpp_static", + "netd_defaults", + ], shared_libs: [ "libbase", "libbinder_ndk", @@ -23,7 +26,6 @@ cc_benchmark { static_libs: [ "libnetd_test_dnsresponder_ndk", "dnsresolver_aidl_interface-lateststable-ndk", - "netd_aidl_interface-lateststable-cpp", // system/netd/server/UidRanges.h "netd_aidl_interface-lateststable-ndk", "netd_event_listener_interface-lateststable-ndk", ], diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp index f423ea38..bc1e7393 100644 --- a/tests/binder_test.cpp +++ b/tests/binder_test.cpp @@ -54,7 +54,6 @@ #include <binder/IPCThreadState.h> #include <bpf/BpfMap.h> #include <bpf/BpfUtils.h> -#include <bpf_shared.h> #include <com/android/internal/net/BnOemNetdUnsolicitedEventListener.h> #include <com/android/internal/net/IOemNetd.h> #include <cutils/multiuser.h> @@ -3769,275 +3768,6 @@ TEST_F(NetdBinderTest, GetFwmarkForNetwork) { EXPECT_TRUE(mNetd->networkDestroy(TEST_NETID1).isOk()); } -namespace { - -TetherOffloadRuleParcel makeTetherOffloadRule(int inputInterfaceIndex, int outputInterfaceIndex, - const std::vector<uint8_t>& destination, - int prefixLength, - const std::vector<uint8_t>& srcL2Address, - const std::vector<uint8_t>& dstL2Address, int pmtu) { - android::net::TetherOffloadRuleParcel parcel; - parcel.inputInterfaceIndex = inputInterfaceIndex; - parcel.outputInterfaceIndex = outputInterfaceIndex; - parcel.destination = destination; - parcel.prefixLength = prefixLength; - parcel.srcL2Address = srcL2Address; - parcel.dstL2Address = dstL2Address; - parcel.pmtu = pmtu; - return parcel; -} - -} // namespace - -// TODO: probably remove the test because TetherOffload* binder calls are deprecated. -TEST_F(NetdBinderTest, DISABLED_TetherOffloadRule) { - // TODO: Perhaps verify invalid interface index once the netd handle the error in methods. - constexpr uint32_t kIfaceInt = 101; - constexpr uint32_t kIfaceExt = 102; - constexpr uint32_t kIfaceNonExistent = 103; - - const std::vector<uint8_t> kAddr6 = {0x20, 0x01, 0x0d, 0xb8, 0xca, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88}; - const std::vector<uint8_t> kSrcMac = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}; - const std::vector<uint8_t> kDstMac = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0b}; - - const std::vector<uint8_t> kInvalidAddr4 = {0xac, 0x0a, 0x0d, 0xb8}; // should be IPv6 address - const std::vector<uint8_t> kInvalidMac = {0xde, 0xad, 0xbe, 0xef}; // should be 6-byte length - - // Invalid IP address, add rule - TetherOffloadRuleParcel rule = makeTetherOffloadRule( - kIfaceExt, kIfaceInt, kInvalidAddr4 /*bad*/, 128, kSrcMac, kDstMac, 1500); - auto status = mNetd->tetherOffloadRuleAdd(rule); - EXPECT_FALSE(status.isOk()); - EXPECT_EQ(EAFNOSUPPORT, status.serviceSpecificErrorCode()); - - // Invalid source L2 address, add rule - rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 128, kInvalidMac /*bad*/, kDstMac, - 1500); - status = mNetd->tetherOffloadRuleAdd(rule); - EXPECT_FALSE(status.isOk()); - EXPECT_EQ(ENXIO, status.serviceSpecificErrorCode()); - - // Invalid destination L2 address, add rule - rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 128, kSrcMac, kInvalidMac /*bad*/, - 1500); - status = mNetd->tetherOffloadRuleAdd(rule); - EXPECT_FALSE(status.isOk()); - EXPECT_EQ(ENXIO, status.serviceSpecificErrorCode()); - - // Invalid IP address, remove rule - rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kInvalidAddr4 /*bad*/, 128, kSrcMac, kDstMac, - 1500); - status = mNetd->tetherOffloadRuleRemove(rule); - EXPECT_FALSE(status.isOk()); - EXPECT_EQ(EAFNOSUPPORT, status.serviceSpecificErrorCode()); - - // Invalid prefix length - rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 64 /*bad*/, kSrcMac, kDstMac, 1500); - status = mNetd->tetherOffloadRuleAdd(rule); - EXPECT_FALSE(status.isOk()); - EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode()); - status = mNetd->tetherOffloadRuleRemove(rule); - EXPECT_FALSE(status.isOk()); - EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode()); - - // Invalid interface index - rule = makeTetherOffloadRule(kIfaceExt, 0, kAddr6, 128, kSrcMac, kDstMac, 1500); - status = mNetd->tetherOffloadRuleAdd(rule); - EXPECT_FALSE(status.isOk()); - EXPECT_EQ(ENODEV, status.serviceSpecificErrorCode()); - rule = makeTetherOffloadRule(0, kIfaceInt, kAddr6, 64, kSrcMac, kDstMac, 1500); - status = mNetd->tetherOffloadRuleRemove(rule); - EXPECT_FALSE(status.isOk()); - EXPECT_EQ(ENODEV, status.serviceSpecificErrorCode()); - - // Invalid pmtu (too low) - rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 128, kSrcMac, kDstMac, 1279); - status = mNetd->tetherOffloadRuleAdd(rule); - EXPECT_FALSE(status.isOk()); - EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode()); - - // Invalid pmtu (too high) - rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 128, kSrcMac, kDstMac, 65536); - status = mNetd->tetherOffloadRuleAdd(rule); - EXPECT_FALSE(status.isOk()); - EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode()); - - // Remove non existent rule. Expect that silently return success if the rule did not exist. - rule = makeTetherOffloadRule(kIfaceNonExistent, kIfaceInt, kAddr6, 128, kSrcMac, kDstMac, 1500); - EXPECT_TRUE(mNetd->tetherOffloadRuleRemove(rule).isOk()); - - // Add and remove rule normally. - rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 128, kSrcMac, kDstMac, 1500); - EXPECT_TRUE(mNetd->tetherOffloadRuleAdd(rule).isOk()); - EXPECT_TRUE(mNetd->tetherOffloadRuleRemove(rule).isOk()); -} - -static bool expectPacket(int fd, uint8_t* ipPacket, ssize_t ipLen) { - constexpr bool kDebug = false; - - uint8_t buf[ETHER_HDR_LEN + 1500]; - - // Wait a bit to ensure that the packet we're interested in has arrived. - // TODO: speed this up. - usleep(100 * 1000); - - ssize_t bytesRead; - ssize_t expectedLen = ipLen + ETHER_HDR_LEN; - while ((bytesRead = read(fd, buf, sizeof(buf))) >= 0) { - if (kDebug) { - std::cerr << fmt::format( - "Expected: {:02x}\n Actual: {:02x}\n", - fmt::join(ipPacket, ipPacket + ipLen, " "), - fmt::join(buf + ETHER_HDR_LEN, buf + ETHER_HDR_LEN + ipLen, " ")); - } - - if (bytesRead != expectedLen) { - continue; - } - - if (!memcmp(ipPacket, buf + ETHER_HDR_LEN, ipLen)) { - return true; - } - } - - return false; -} - -static bool tcQdiscExists(const std::string& interface) { - std::string command = StringPrintf("tc qdisc show dev %s", interface.c_str()); - std::vector<std::string> lines = runCommand(command); - for (const auto& line : lines) { - if (StartsWith(line, "qdisc clsact ffff:")) return true; - } - return false; -} - -static bool tcFilterExists(const std::string& interface) { - std::string command = StringPrintf("tc filter show dev %s ingress", interface.c_str()); - std::vector<std::string> lines = runCommand(command); - const std::basic_regex regex("^filter .* bpf .* prog_offload_schedcls_tether_.*$"); - for (const auto& line : lines) { - if (std::regex_match(Trim(line), regex)) return true; - } - return false; -} - -// TODO: probably remove the test because TetherOffload* binder calls are deprecated. -TEST_F(NetdBinderTest, DISABLED_TetherOffloadForwarding) { - SKIP_IF_EXTENDED_BPF_NOT_SUPPORTED; - - constexpr const char* kDownstreamPrefix = "2001:db8:2::/64"; - - // 1500-byte packet. - constexpr unsigned short kPayloadLen = 1500 - sizeof(ipv6hdr); - struct packet { - ipv6hdr hdr; - char data[kPayloadLen]; - } __attribute__((packed)) pkt = { - .hdr = - { - .version = 6, - .payload_len = htons(kPayloadLen), - .nexthdr = 59, // No next header. - .hop_limit = 64, - .saddr = {{{0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}}, - .daddr = {{{0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0f, 0x00, 0xca, 0xfe}}}, - }, - }; - ASSERT_EQ(1500U, sizeof(pkt)); - - // Use one of the test's tun interfaces as upstream. - // It must be part of a network or it will not have the clsact attached. - const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, - INetd::PERMISSION_NONE, false, false); - EXPECT_TRUE(mNetd->networkCreate(config).isOk()); - EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); - int fd1 = sTun.getFdForTesting(); - EXPECT_TRUE(tcQdiscExists(sTun.name())); - - // Create our own tap as a downstream. - TunInterface tap; - ASSERT_EQ(0, tap.init(true /* isTap */)); - ASSERT_LE(tap.name().size(), static_cast<size_t>(IFNAMSIZ)); - int fd2 = tap.getFdForTesting(); - - // Set it to nonblocking so that expectPacket can work. - int flags = fcntl(fd2, F_GETFL, 0); - fcntl(fd2, F_SETFL, flags | O_NONBLOCK); - - // Downstream interface setup. Add to local network, add directly-connected route, etc. - binder::Status status = mNetd->networkAddInterface(INetd::LOCAL_NET_ID, tap.name()); - EXPECT_TRUE(status.isOk()) << status.exceptionMessage(); - status = mNetd->tetherInterfaceAdd(tap.name()); - EXPECT_TRUE(status.isOk()) << status.exceptionMessage(); - expectTetherInterfaceConfigureForIPv6Router(tap.name()); - EXPECT_TRUE(tcQdiscExists(tap.name())); - - // Can't easily use INetd::NEXTHOP_NONE because it is a String16 constant. Use "" instead. - status = mNetd->networkAddRoute(INetd::LOCAL_NET_ID, tap.name(), kDownstreamPrefix, ""); - EXPECT_TRUE(status.isOk()) << status.exceptionMessage(); - - // Set up forwarding. All methods take intIface first and extIface second. - status = mNetd->tetherAddForward(tap.name(), sTun.name()); - EXPECT_TRUE(status.isOk()) << status.exceptionMessage(); - status = mNetd->ipfwdAddInterfaceForward(tap.name(), sTun.name()); - EXPECT_TRUE(status.isOk()) << status.exceptionMessage(); - EXPECT_TRUE(tcFilterExists(sTun.name())); - - std::vector<uint8_t> kDummyMac = {02, 00, 00, 00, 00, 00}; - uint8_t* daddr = reinterpret_cast<uint8_t*>(&pkt.hdr.daddr); - std::vector<uint8_t> dstAddr(daddr, daddr + sizeof(pkt.hdr.daddr)); - - TetherOffloadRuleParcel rule = makeTetherOffloadRule(sTun.ifindex(), tap.ifindex(), dstAddr, - 128, kDummyMac, kDummyMac, sizeof(pkt)); - status = mNetd->tetherOffloadRuleAdd(rule); - EXPECT_TRUE(status.isOk()) << status.exceptionMessage(); - - // Set data limit to one byte less than two packets. - // If you get rid of the '- 1' then the second packet will get forwarded - // and the EXPECT_FALSE(expectPacket(...)) a dozen lines down will fail. - status = mNetd->tetherOffloadSetInterfaceQuota(sTun.ifindex(), sizeof(pkt) * 2 - 1); - EXPECT_TRUE(status.isOk()) << status.exceptionMessage(); - - // Receive a packet on sTun. - EXPECT_EQ((ssize_t)sizeof(pkt), write(fd1, &pkt, sizeof(pkt))); - - // Expect a packet identical to pkt, except with a TTL of 63. - struct packet pkt2 = pkt; - ASSERT_EQ(1500U, sizeof(pkt2)); - pkt2.hdr.hop_limit = pkt.hdr.hop_limit - 1; - EXPECT_TRUE(expectPacket(fd2, (uint8_t*)&pkt2, sizeof(pkt2))); - - // Receive a second packet on sTun. - EXPECT_EQ((ssize_t)sizeof(pkt), write(fd1, &pkt, sizeof(pkt))); - - // Should fail to forward due to quota limit. - EXPECT_FALSE(expectPacket(fd2, (uint8_t*)&pkt2, sizeof(pkt2))); - - // Clean up. - EXPECT_TRUE(mNetd->tetherOffloadRuleRemove(rule).isOk()); - - TetherStatsParcel tetherStats; - EXPECT_TRUE(mNetd->tetherOffloadGetAndClearStats(sTun.ifindex(), &tetherStats).isOk()); - EXPECT_EQ("", tetherStats.iface); - EXPECT_EQ(static_cast<int64_t>(sizeof(pkt)), tetherStats.rxBytes); - EXPECT_EQ(1, tetherStats.rxPackets); - EXPECT_EQ(0, tetherStats.txBytes); - EXPECT_EQ(0, tetherStats.txPackets); - EXPECT_EQ(sTun.ifindex(), tetherStats.ifIndex); - - EXPECT_TRUE(mNetd->ipfwdRemoveInterfaceForward(tap.name(), sTun.name()).isOk()); - EXPECT_TRUE(mNetd->tetherRemoveForward(tap.name(), sTun.name()).isOk()); - EXPECT_TRUE(mNetd->networkRemoveRoute(INetd::LOCAL_NET_ID, tap.name(), kDownstreamPrefix, "") - .isOk()); - EXPECT_TRUE(mNetd->tetherInterfaceRemove(tap.name()).isOk()); - EXPECT_TRUE(mNetd->networkRemoveInterface(INetd::LOCAL_NET_ID, tap.name()).isOk()); - EXPECT_TRUE(mNetd->networkRemoveInterface(TEST_NETID1, sTun.name()).isOk()); -} - TEST_F(NetdBinderTest, TestServiceDump) { sp<IBinder> binder = INetd::asBinder(mNetd); ASSERT_NE(nullptr, binder); @@ -4119,40 +3849,6 @@ TEST_F(NetdBinderTest, TestServiceDump) { } } -TEST_F(NetdBinderTest, DeprecatedTetherOffloadRuleAdd) { - TetherOffloadRuleParcel emptyRule; - auto status = mNetd->tetherOffloadRuleAdd(emptyRule); - ASSERT_FALSE(status.isOk()); - ASSERT_EQ(status.exceptionCode(), binder::Status::EX_UNSUPPORTED_OPERATION); -} - -TEST_F(NetdBinderTest, DeprecatedTetherOffloadRuleRemove) { - TetherOffloadRuleParcel emptyRule; - auto status = mNetd->tetherOffloadRuleRemove(emptyRule); - ASSERT_FALSE(status.isOk()); - ASSERT_EQ(status.exceptionCode(), binder::Status::EX_UNSUPPORTED_OPERATION); -} - -TEST_F(NetdBinderTest, DeprecatedTetherOffloadGetStats) { - std::vector<TetherStatsParcel> tetherStatsList; - auto status = mNetd->tetherOffloadGetStats(&tetherStatsList); - ASSERT_FALSE(status.isOk()); - ASSERT_EQ(status.exceptionCode(), binder::Status::EX_UNSUPPORTED_OPERATION); -} - -TEST_F(NetdBinderTest, DeprecatedTetherOffloadSetInterfaceQuota) { - auto status = mNetd->tetherOffloadSetInterfaceQuota(0 /* ifIndex */, 0 /* quotaBytes */); - ASSERT_FALSE(status.isOk()); - ASSERT_EQ(status.exceptionCode(), binder::Status::EX_UNSUPPORTED_OPERATION); -} - -TEST_F(NetdBinderTest, DeprecatedTetherOffloadGetAndClearStats) { - TetherStatsParcel tetherStats; - auto status = mNetd->tetherOffloadGetAndClearStats(0 /* ifIndex */, &tetherStats); - ASSERT_FALSE(status.isOk()); - ASSERT_EQ(status.exceptionCode(), binder::Status::EX_UNSUPPORTED_OPERATION); -} - namespace { // aliases for better reading |