diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp index 19dd492b67..2878f79458 100644 --- a/Tethering/apex/Android.bp +++ b/Tethering/apex/Android.bp @@ -102,15 +102,14 @@ apex { "dscpPolicy.o", "netd.o", "offload.o", - "offload@mainline.o", "test.o", - "test@mainline.o", ], apps: [ "ServiceConnectivityResources", ], prebuilts: [ "current_sdkinfo", + "netbpfload.31rc", "netbpfload.33rc", "netbpfload.35rc", "ot-daemon.34rc", diff --git a/bpf/dns_helper/DnsBpfHelper.cpp b/bpf/dns_helper/DnsBpfHelper.cpp index 0719ade395..cf2fa2b736 100644 --- a/bpf/dns_helper/DnsBpfHelper.cpp +++ b/bpf/dns_helper/DnsBpfHelper.cpp @@ -32,12 +32,44 @@ namespace net { } \ } while (0) +// copied from BpfHandler.cpp +static bool mainlineNetBpfLoadDone() { + return !access("/sys/fs/bpf/netd_shared/mainline_done", F_OK); +} + +// copied from BpfHandler.cpp +static inline void waitForNetProgsLoaded() { + // infinite loop until success with 5/10/20/40/60/60/60... delay + for (int delay = 5;; delay *= 2) { + if (delay > 60) delay = 60; + if (base::WaitForProperty("init.svc.mdnsd_netbpfload", "stopped", std::chrono::seconds(delay)) + && mainlineNetBpfLoadDone()) return; + LOG(WARNING) << "Waited " << delay << "s for init.svc.mdnsd_netbpfload=stopped, still waiting."; + } +} + base::Result DnsBpfHelper::init() { - if (!android::modules::sdklevel::IsAtLeastT()) { - LOG(ERROR) << __func__ << ": Unsupported before Android T."; + if (!android::modules::sdklevel::IsAtLeastS()) { + LOG(ERROR) << __func__ << ": Unsupported before Android S."; return base::Error(EOPNOTSUPP); } + if (!android::modules::sdklevel::IsAtLeastT()) { + LOG(INFO) << "performing Android S mainline NetBpfload magic!"; + if (!mainlineNetBpfLoadDone()) { + // We're on S/Sv2 & it's the first time netd is starting up (unless crashlooping) + if (!base::SetProperty("ctl.start", "mdnsd_netbpfload")) { + LOG(ERROR) << "Failed to set property ctl.start=mdnsd_netbpfload, see dmesg for reason."; + return base::Error(ENOEXEC); + } + + LOG(INFO) << "Waiting for Networking BPF programs"; + waitForNetProgsLoaded(); + LOG(INFO) << "Networking BPF programs are loaded"; + } + return {}; + } + RETURN_IF_RESULT_NOT_OK(mConfigurationMap.init(CONFIGURATION_MAP_PATH)); RETURN_IF_RESULT_NOT_OK(mUidOwnerMap.init(UID_OWNER_MAP_PATH)); RETURN_IF_RESULT_NOT_OK(mDataSaverEnabledMap.init(DATA_SAVER_ENABLED_MAP_PATH)); diff --git a/bpf/loader/Android.bp b/bpf/loader/Android.bp index b08913a2c5..780fe20d84 100644 --- a/bpf/loader/Android.bp +++ b/bpf/loader/Android.bp @@ -56,11 +56,22 @@ cc_binary { installable: false, } -// Versioned netbpfload init rc: init system will process it only on api T/33+ devices +// Versioned netbpfload init rc: init system will process it only on api R/30 S/31 Sv2/32 devices // Note: R[30] S[31] Sv2[32] T[33] U[34] V[35]) // // For details of versioned rc files see: // https://android.googlesource.com/platform/system/core/+/HEAD/init/README.md#versioned-rc-files-within-apexs +// +// However, .Xrc versioning doesn't work on S, so we use unversioned, and thus *do* trigger on R, +// luckily nothing ever uses the new service on R, so you can think of it as being S/Sv2 only +prebuilt_etc { + name: "netbpfload.31rc", + src: "netbpfload.31rc", + filename: "netbpfload.rc", // intentional: .31rc wouldn't take effect on S + installable: false, +} + +// Versioned netbpfload init rc: init system will process it only on api T/33+ devices prebuilt_etc { name: "netbpfload.33rc", src: "netbpfload.33rc", diff --git a/bpf/loader/NetBpfLoad.cpp b/bpf/loader/NetBpfLoad.cpp index 9c62e7440f..bad506f7c0 100644 --- a/bpf/loader/NetBpfLoad.cpp +++ b/bpf/loader/NetBpfLoad.cpp @@ -122,6 +122,7 @@ static constexpr bool specified(domain d) { struct Location { const char* const dir = ""; const char* const prefix = ""; + const bool t_plus = true; }; // Returns the build type string (from ro.build.type). @@ -1216,8 +1217,9 @@ static bool exists(const char* const path) { const Location locations[] = { // S+ Tethering mainline module (network_stack): tether offload { - .dir = BPFROOT "/", + .dir = BPFROOT "/tethering/", .prefix = "tethering/", + .t_plus = false, }, // T+ Tethering mainline module (shared with netd & system server) // netutils_wrapper (for iptables xt_bpf) has access to programs @@ -1412,6 +1414,13 @@ static bool isWear() { } static int doLoad(char** argv, char * const envp[]) { + if (!isAtLeastS) { + ALOGE("Impossible - not reachable on Android