Das eBPF-Tool für Netzwerk-Traffic verwendet eine Kombination aus Kernel- und Nutzerbereichsimplementierung, um die Netzwerknutzung auf dem Gerät seit dem letzten Gerätestart zu überwachen. Es bietet zusätzliche Funktionen wie das Taggen von Sockets, das Trennen von Vordergrund- und Hintergrund-Traffic sowie eine Firewall pro UID, um Apps je nach Telefonstatus den Netzwerkzugriff zu verweigern. Die vom Tool erhobenen Statistiken werden in einer Kernel-Datenstruktur namens eBPF maps
gespeichert. Das Ergebnis wird von Diensten wie NetworkStatsService
verwendet, um seit dem letzten Start persistente Traffic-Statistiken bereitzustellen.
Beispiele und Quelle
Die Änderungen im Nutzerbereich betreffen hauptsächlich die Projekte system/netd
und framework/base
. Die Entwicklung erfolgt in AOSP, sodass der AOSP-Code immer auf dem neuesten Stand ist. Die Quelle befindet sich hauptsächlich unter
system/netd/server/TrafficController*
,
system/netd/bpfloader
und
system/netd/libbpf/
.
Einige erforderliche Framework-Änderungen sind auch in framework/base/
und system/core
enthalten.
Implementierung
Ab Android 9 müssen Android-Geräte mit Kernel 4.9 oder höher, die ursprünglich mit der P-Version ausgeliefert wurden, anstelle von xt_qtaguid
die eBPF-basierte Abrechnung zur Überwachung des Netzwerkverkehrs verwenden. Die neue Infrastruktur ist flexibler und wartungsfreundlicher und erfordert keinen Kernelcode außerhalb des Baums.
Die wichtigsten Designunterschiede zwischen der Legacy- und der eBPF-basierten Traffic-Überwachung sind in Abbildung 1 dargestellt.
Abbildung 1: Unterschiede zwischen dem Design für die Traffic-Überwachung mit Legacy-Methoden (links) und eBPF (rechts)
Das neue trafficController
-Design basiert auf dem eBPF-Filter pro cgroup
sowie dem xt_bpf
-Netfilter-Modul im Kernel. Diese eBPF-Filter werden auf die Paketübertragung/-empfang angewendet, wenn die Pakete den Filter durchlaufen. Der cgroup
-eBPF-Filter befindet sich auf der Transportschicht und ist dafür verantwortlich, den Traffic anhand der Socket-UID und der Userspace-Einstellung der richtigen UID zuzuordnen.
Der xt_bpf
-Netfilter ist an die Kette bw_raw_PREROUTING
und bw_mangle_POSTROUTING
angehängt und dafür verantwortlich, den Traffic für die richtige Schnittstelle zu zählen.
Beim Booten erstellt der Userspace-Prozess trafficController
die eBPF-Maps, die für die Datenerhebung verwendet werden, und pinnt alle Maps als virtuelle Datei unter sys/fs/bpf
.
Der privilegierte Prozess bpfloader
lädt dann das vorkompilierte eBPF-Programm in den Kernel und hängt es an den richtigen cgroup
an. Es gibt einen einzelnen Stamm-cgroup
für den gesamten Traffic. Daher sollten alle Prozesse standardmäßig in diesem cgroup
enthalten sein.
Zur Laufzeit kann das trafficController
einen Socket taggen/enttaggen, indem es in traffic_cookie_tag_map
und traffic_uid_counterSet_map
schreibt. Die NetworkStatsService
kann die Daten zu Verkehrsstatistiken aus traffic_tag_stats_map
, traffic_uid_stats_map
und traffic_iface_stats_map
lesen.
Neben der Funktion zum Erfassen von Traffic-Statistiken sind die eBPF-Filter trafficController
und cgroup
auch dafür verantwortlich, Traffic von bestimmten UIDs je nach Telefoneinstellungen zu blockieren. Die UID-basierte Funktion zum Blockieren von Netzwerk-Traffic ersetzt das xt_owner
-Modul im Kernel. Der Detailmodus kann durch Schreiben in traffic_powersave_uid_map
, traffic_standby_uid_map
und traffic_dozable_uid_map
konfiguriert werden.
Die neue Implementierung folgt der alten xt_qtaguid
-Modulimplementierung. TrafficController
und NetworkStatsService
werden also entweder mit der alten oder der neuen Implementierung ausgeführt. Wenn die App öffentliche APIs verwendet, sollte es keinen Unterschied machen, ob xt_qtaguid
- oder eBPF-Tools im Hintergrund verwendet werden.
Wenn der Geräte-Kernel auf dem gemeinsamen Android-Kernel 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 oder höher) basiert, sind keine Änderungen an HALs, Treibern oder Kernelcode erforderlich, um das neue eBPF-Tool zu implementieren.
Voraussetzungen
In der Kernelkonfiguration MÜSSEN die folgenden Konfigurationen aktiviert sein:
CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_INET_UDP_DIAG=y
Der VTS-Kernelkonfigurationstest ist hilfreich, um zu prüfen, ob die richtige Konfiguration aktiviert ist.
Einstellung des alten xt_qtaguid
Das neue eBPF-Tool ersetzt das Modul xt_qtaguid
und das Modul xt_owner
, auf dem es basiert. Wir werden das xt_qtaguid
-Modul aus dem Android-Kernel entfernen und die unnötigen Konfigurationen deaktivieren.
In Android 9 ist das xt_qtaguid
-Modul auf allen Geräten aktiviert. Alle öffentlichen APIs, die die Proc-Datei des xt_qtaguid
-Moduls direkt lesen, werden jedoch in den NetworkManagement
-Dienst verschoben.
Je nach Gerätekernelversion und erstem API-Level weiß der NetworkManagement
-Dienst, ob eBPF-Tools aktiviert sind, und wählt das richtige Modul für jede Statistik zur App-Netzwerknutzung aus. Apps mit SDK-Level 28 und höher wird durch sepolicy der Zugriff auf xt_qtaguid
-Proc-Dateien verwehrt.
In der nächsten Android-Version nach Version 9 wird der App-Zugriff auf diese xt_qtaguid
-Proc-Dateien vollständig blockiert. Wir werden das xt_qtaguid
-Modul aus den neuen gemeinsamen Android-Kerneln entfernen. Nachdem es entfernt wurde, aktualisieren wir die Android-Basiskonfiguration für diese Kernelversion, um das xt_qtaguid
-Modul explizit zu deaktivieren. Das xt_qtaguid
-Modul wird vollständig eingestellt, wenn die Mindestanforderung an die Kernelversion für eine Android-Version 4.9 oder höher ist.
In der Android 9-Version müssen nur Geräte, die mit der Android 9-Version auf den Markt kommen, die neue eBPF-Funktion haben. Bei Geräten, die mit einem Kernel ausgeliefert wurden, der eBPF-Tools unterstützt, empfehlen wir, beim Upgrade auf Android 9 auf die neue eBPF-Funktion zu aktualisieren. Es gibt keinen CTS-Test, um dieses Update zu erzwingen.
Zertifizierungsstufe
Sie sollten regelmäßig Patches aus den gemeinsamen Android-Kernels und dem Android AOSP-Main-Branch übernehmen. Achten Sie darauf, dass Ihre Implementierung die anwendbaren VTS- und CTS-Tests, die netd_unit_test
und die libbpf_test
besteht.
Testen
Es gibt Kernel-Netzwerktests, mit denen Sie prüfen können, ob die erforderlichen Funktionen aktiviert und die erforderlichen Kernel-Patches rückportiert wurden. Die Tests sind als Teil der VTS-Tests für Android 9-Releases integriert. In system/netd/
(netd_unit_test
und libbpf_test
) sind einige Unittests enthalten. In netd_integration_test
sind einige Tests enthalten, um das Gesamtverhalten des neuen Tools zu validieren.
CTS und CTS‑Prüfung
Da beide Module zur Traffic-Überwachung in Android 9 unterstützt werden, gibt es keinen CTS-Test, der die Implementierung des neuen Moduls auf allen Geräten erzwingt. Für Geräte mit einer Kernelversion höher als 4.9, die ursprünglich mit Android 9 ausgeliefert wurden (d.h. das erste API-Level >= 28), gibt es jedoch CTS-Tests auf GSI, um zu prüfen, ob das neue Modul richtig konfiguriert ist. Mit alten CTS-Tests wie TrafficStatsTest
, NetworkUsageStatsTest
und CtsNativeNetTestCases
kann überprüft werden, ob das Verhalten mit dem alten UID-Modul übereinstimmt.
Manuelle Tests
Es gibt einige Unittests in system/netd/
(netd_unit_test
, netd_integration_test
und libbpf_test
). Es gibt dumpsys-Unterstützung für die manuelle Überprüfung des Status. Der Befehl dumpsys netd
zeigt den grundlegenden Status des trafficController
-Moduls und ob eBPF korrekt aktiviert ist. Wenn eBPF aktiviert ist, zeigt der Befehl dumpsys netd trafficcontroller
den detaillierten Inhalt jeder eBPF-Karte an, einschließlich der Informationen zu getaggten Sockets, Statistiken pro Tag, UID und iface sowie der Übereinstimmung der Eigentümer-UID.
Teststandorte
CTS-Tests befinden sich unter:
- https://android.googlesource.com/platform/cts/+/android16-release/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
- https://android.googlesource.com/platform/cts/+/android16-release/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
- https://android.googlesource.com/platform/system/netd/+/android16-release/tests/bpf_base_test.cpp
VTS-Tests befinden sich unter https://android.googlesource.com/kernel/tests/+/android16-release/net/test/bpf_test.py.
Unittests befinden sich unter: