From 23ff703f7a3d62d431d66a536940111b1a235727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Tue, 23 Nov 2021 06:23:43 -0800 Subject: [PATCH] better compatibility for unusual Qualcomm/Mediatek cellular ARPHRD_* values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit see kernel/private/wembley/+/refs/heads/tm-4.19/include/uapi/linux/if_arp.h which has #define ARPHRD_PUREIP 520 (and is a Mediatek based device) or Qualcomm based Pixel 3 and older kernels (<=4.9) which #define ARPHRD_RAWIP 530 (unlike Pixel 4/5 which are 4.14/4.19 and use the upstream ARPHRD_RAWIP of 519) We stop supporting 520/530 starting with 5.11+ since those as GKI 2.0 only kernels cannot be using non-upstream-ed constants (btw. this is probably true for 5.10-S as well, but let's play it safe). For pre-5.11 we're lucky because even now (with 5.15 released) upstream has yet to define an ARPHRD_* for either one of 520 or 530, so there's no harm in 'squatting' on this unused space. This approach also means there's absolutely no change in behaviour on pre-launch-T devices, since they all are at most running 5.10 kernels. We'll be able to get rid of this code in the far future once we stop shipping mainline tethering updates to pre-5.10 Mediatek or pre-4.14 Qualcomm devices. This will likely be many years. Test: TreeHugger Bug: 207057951 Signed-off-by: Maciej Żenczykowski Change-Id: I767b5fc56bc826e088507aea8ae7a30aa8aa424a --- ...ndroid_networkstack_tethering_BpfUtils.cpp | 53 ++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/Tethering/jni/com_android_networkstack_tethering_BpfUtils.cpp b/Tethering/jni/com_android_networkstack_tethering_BpfUtils.cpp index 9838bf180e..f9e482436d 100644 --- a/Tethering/jni/com_android_networkstack_tethering_BpfUtils.cpp +++ b/Tethering/jni/com_android_networkstack_tethering_BpfUtils.cpp @@ -26,6 +26,7 @@ #include #include #include +#include // TODO: use unique_fd. #define BPF_FD_JUST_USE_INT @@ -158,6 +159,37 @@ static int hardwareAddressType(const char* interface) { return rv; } +// ----------------------------------------------------------------------------- +// TODO - just use BpfUtils.h once that is available in sc-mainline-prod and has kernelVersion() +// +// In the mean time copying verbatim from: +// system/bpf/libbpf_android/include/bpf/BpfUtils.h +// and +// system/bpf/libbpf_android/BpfUtils.cpp + +#define KVER(a, b, c) (((a) << 24) + ((b) << 16) + (c)) + +static unsigned kernelVersion() { + struct utsname buf; + int ret = uname(&buf); + if (ret) return 0; + + unsigned kver_major; + unsigned kver_minor; + unsigned kver_sub; + char discard; + ret = sscanf(buf.release, "%u.%u.%u%c", &kver_major, &kver_minor, &kver_sub, &discard); + // Check the device kernel version + if (ret < 3) return 0; + + return KVER(kver_major, kver_minor, kver_sub); +} + +static inline bool isAtLeastKernelVersion(unsigned major, unsigned minor, unsigned sub) { + return kernelVersion() >= KVER(major, minor, sub); +} +// ----------------------------------------------------------------------------- + static jboolean com_android_networkstack_tethering_BpfUtils_isEthernet(JNIEnv* env, jobject clazz, jstring iface) { ScopedUtfChars interface(env, iface); @@ -170,13 +202,30 @@ static jboolean com_android_networkstack_tethering_BpfUtils_isEthernet(JNIEnv* e return false; } + // Backwards compatibility with pre-GKI kernels that use various custom + // ARPHRD_* for their cellular interface + switch (rv) { + // ARPHRD_PUREIP on at least some Mediatek Android kernels + // example: wembley with 4.19 kernel + case 520: + // in Linux 4.14+ rmnet support was upstreamed and ARHRD_RAWIP became 519, + // but it is 530 on at least some Qualcomm Android 4.9 kernels with rmnet + // example: Pixel 3 family + case 530: + // >5.4 kernels are GKI2.0 and thus upstream compatible, however 5.10 + // shipped with Android S, so (for safety) let's limit ourselves to + // >5.10, ie. 5.11+ as a guarantee we're on Android T+ and thus no + // longer need this non-upstream compatibility logic + static bool is_pre_5_11_kernel = !isAtLeastKernelVersion(5, 11, 0); + if (is_pre_5_11_kernel) return false; + } + switch (rv) { case ARPHRD_ETHER: return true; case ARPHRD_NONE: case ARPHRD_PPP: - case ARPHRD_RAWIP: // in Linux 4.14+ rmnet support was upstreamed and this is 519 - case 530: // this is ARPHRD_RAWIP on some Android 4.9 kernels with rmnet + case ARPHRD_RAWIP: return false; default: jniThrowExceptionFmt(env, "java/io/IOException",