Narzędzie do monitorowania ruchu sieciowego eBPF korzysta z kombinacji implementacji w przestrzeni jądra i użytkownika, aby monitorować wykorzystanie sieci na urządzeniu od ostatniego uruchomienia. Zapewnia ona dodatkowe funkcje, takie jak oznaczanie gniazd, oddzielanie ruchu w tle i firewall na podstawie UID, aby blokować dostęp aplikacji do sieci w zależności od stanu telefonu. Statystyki zebrane przez narzędzie są przechowywane w strukturze danych jądra o nazwie eBPF maps
, a ich wynik jest używany przez usługi takie jak NetworkStatsService
do dostarczania trwałych statystyk ruchu od ostatniego uruchomienia.
Przykłady i źródło
Zmiany w przestrzeni użytkownika dotyczą głównie projektów system/netd
i framework/base
. Programy są prowadzone w AOSP, więc kod AOSP będzie zawsze aktualny. Źródło znajduje się głównie w system/netd/server/TrafficController*
, system/netd/bpfloader
i system/netd/libbpf/
.
Niektóre niezbędne zmiany w ramach znajdują się też w dokumentach framework/base/
i system/core
.
Implementacja
Począwszy od Androida 9 urządzenia z Androidem z jądrem w wersji 4.9 lub nowszej, które zostały pierwotnie dostarczone z wersją P, MUSZĄ używać rejestrowania monitorowania ruchu sieciowego na podstawie eBPF zamiast xt_qtaguid
. Nowa infrastruktura jest bardziej elastyczna i łatwiejsza w utrzymaniu, a dodatkowo nie wymaga kodu jądra poza drzewem.
Rysunek 1 przedstawia główne różnice w projektowaniu między starszym a eBPF monitorowaniem ruchu.
Rysunek 1. Różnice między starszym (po lewej) a nową (po prawej) wersją monitorowania ruchu
Nowa architektura trafficController
opiera się na filtrach eBPF na poziomie cgroup
oraz module netfilter xt_bpf
w jądrze. Filtry eBPF są stosowane
do pakietów tx/rx, gdy przechodzą przez filtr. Filtr eBPF cgroup
znajduje się na warstwie transportowej i odpowiada za zliczanie ruchu w stosunku do właściwego identyfikatora UID w zależności od identyfikatora gniazda oraz ustawień przestrzeni użytkownika.
Filtr sieci xt_bpf
jest podłączony do łańcucha bw_raw_PREROUTING
i bw_mangle_POSTROUTING
i odpowiada za zliczanie ruchu w odniesieniu do właściwego interfejsu.
Podczas uruchamiania proces w przestrzeni użytkownika trafficController
tworzy mapy eBPF służące do zbierania danych i przypina wszystkie mapy jako plik wirtualny w folderze sys/fs/bpf
.
Następnie proces uprzywilejowany bpfloader
wczytuje skompilowany program eBPF do jądra i dołącza go do odpowiedniego cgroup
. W przypadku całego ruchu istnieje jeden główny obiekt cgroup
, więc domyślnie w tym cgroup
powinien być uwzględniony cały proces.
W czasie wykonywania trafficController
może dodawać i usuwać tagi z gniazda, zapisując w nim dane za pomocą funkcji traffic_cookie_tag_map
i traffic_uid_counterSet_map
. NetworkStatsService
może odczytywać dane statystyczne o ruchu z usług traffic_tag_stats_map
, traffic_uid_stats_map
i traffic_iface_stats_map
.
Oprócz funkcji zbierania statystyk ruchu filtr eBPF trafficController
i cgroup
odpowiada też za blokowanie ruchu z określonych identyfikatorów użytkownika w zależności od ustawień telefonu. Funkcja blokowania ruchu sieciowego na podstawie UID zastępuje moduł xt_owner
w jądrze, a tryb szczegółowy można skonfigurować, zapisując dane w plikach traffic_powersave_uid_map
, traffic_standby_uid_map
i traffic_dozable_uid_map
.
Nowa implementacja jest zgodna ze starszą implementacją modułu xt_qtaguid
, więc moduły TrafficController
i NetworkStatsService
będą działać z wersją starszą lub nowszą. Jeśli aplikacja korzysta z publicznych interfejsów API, nie powinno mieć znaczenia, czy w tle są używane narzędzia xt_qtaguid
czy eBPF.
Jeśli jądro urządzenia jest oparte na wspólnym jądrze Androida w wersji 4.9 (SHA2 39c856663dcc81739e52b02b77d6af259eb838f6 lub nowszej), nie trzeba modyfikować interfejsów HAL, sterowników ani kodu jądra, aby wdrożyć nowe narzędzie eBPF.
Wymagania
W konfiguracji jądra MUSZĄ być włączone te ustawienia:
CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_INET_UDP_DIAG=y
Test konfiguracji jądra VTS jest przydatny podczas sprawdzania, czy włączona jest prawidłowa konfiguracja.
Proces wycofywania starszej wersji atrybutu xt_qtaguid
Nowe narzędzie eBPF zastępuje moduł xt_qtaguid
i moduł xt_owner
, na których się opiera. Zaczniemy usuwać moduł xt_qtaguid
z jądra Androida i wyłączać jego niepotrzebne konfiguracje.
W wersji Androida 9 moduł xt_qtaguid
jest włączony na wszystkich urządzeniach, ale wszystkie publiczne interfejsy API, które bezpośrednio odczytują plik xt_qtaguid
, są przenoszone do usługi NetworkManagement
.
W zależności od wersji jądra urządzenia i pierwszego poziomu interfejsu API usługa NetworkManagement
wie, czy narzędzia eBPF są włączone, i wybiera odpowiedni moduł do uzyskania statystyk dotyczących wykorzystania sieci przez każdą aplikację. Aplikacje z poziomem pakietu SDK 28 lub wyższym nie mają dostępu do plików xt_qtaguid
proc. z powodu ograniczeń w zasadach zabezpieczeń.
W następnej wersji Androida po 9 będzie całkowicie zablokowany dostęp aplikacji do tych plików xt_qtaguid
proc. Zaczniemy usuwać moduł xt_qtaguid
z nowych wspólnych jąder Androida. Po usunięciu tego modułu zaktualizujemy podstawową konfigurację Androida dla tej wersji jądra, aby wyraźnie wyłączyć moduł xt_qtaguid
. Moduł xt_qtaguid
zostanie całkowicie wycofany, gdy minimalne wymagania dotyczące wersji jądra dla wersji Androida będą wynosić 4.9 lub nowszą.
W wersji Androida 9 nowa funkcja eBPF jest wymagana tylko na urządzeniach, które są uruchamiane z Androidem 9. W przypadku urządzeń dostarczonych z jądrem, które może obsługiwać narzędzia eBPF, zalecamy zaktualizowanie go do nowej funkcji eBPF podczas przechodzenia na Androida 9. Nie ma testu CTS, który wymuszałby tę aktualizację.
Weryfikacja
Należy regularnie pobierać poprawki z powszechnie używanych jąder Androida i Androida AOSP. Upewnij się, że Twoja implementacja przeszła odpowiednie testy VTS i CTS, netd_unit_test
oraz libbpf_test
.
Testowanie
Dostępne są testy jądra systemu, które sprawdzają, czy wymagane funkcje są włączone, a wymagane poprawki jądra zostały przywrócone. Testy są zintegrowane w ramach testów VTS w ramach wersji Androida 9. W system/netd/
znajdują się testy jednostkowe (netd_unit_test
i libbpf_test
). W netd_integration_test
znajdują się testy, które sprawdzają ogólne działanie nowego narzędzia.
CTS i weryfikator CTS
Oba moduły monitorowania ruchu są obsługiwane w wersji Androida 9, więc nie ma testu CTS, który wymusiłby implementację nowego modułu na wszystkich urządzeniach. Jednak w przypadku urządzeń z jądrem nowszym niż 4.9, które pierwotnie były dostarczane z wersją Androida 9 (czyli z poziomem interfejsu API ≥ 28), dostępne są testy CTS na GSI, które sprawdzają, czy nowy moduł jest prawidłowo skonfigurowany. Stare testy CTS, takie jak TrafficStatsTest
, NetworkUsageStatsTest
i CtsNativeNetTestCases
, można wykorzystać do zweryfikowania działania pod kątem spójności ze starym modułem UID.
Testy ręczne
W system/netd/
są dostępne testy jednostkowe (netd_unit_test
,
netd_integration_test
i
libbpf_test
).
Aby ręcznie sprawdzić stan, możesz użyć narzędzia dumpsys. Polecenie dumpsys netd
pokazuje podstawowy stan modułu trafficController
oraz to, czy funkcja eBPF jest prawidłowo włączona. Jeśli eBPF jest włączone, polecenie dumpsys netd trafficcontroller
wyświetla szczegółowe informacje o każdej mapie eBPF, w tym informacje o otagowanych gniazdach, statystyki dotyczące tagów, UID i interfejsów oraz dopasowanie UID właściciela.
Testowanie lokalizacji
Testy CTS znajdują się pod tymi adresami:
- https://android.googlesource.com/platform/cts/+/main/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
- https://android.googlesource.com/platform/cts/+/main/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
- https://android.googlesource.com/platform/system/netd/+/main/tests/bpf_base_test.cpp
Testy VTS znajdują się pod adresem https://android.googlesource.com/kernel/tests/+/main/net/test/bpf_test.py.
Testy jednostkowe znajdują się w tych miejscach:
- https://android.googlesource.com/platform/system/netd/+/main/libbpf/BpfNetworkStatsTest.cpp
- https://android.googlesource.com/platform/system/netd/+/main/server/TrafficControllerTest.cpp