Narzędzie do analizy ruchu sieciowego eBPF wykorzystuje połączenie implementacji w przestrzeni jądra i użytkownika do monitorowania wykorzystania sieci na urządzeniu od ostatniego uruchomienia. Zapewnia dodatkowe funkcje, takie jak tagowanie gniazd, rozdzielanie ruchu na pierwszym planie i w tle oraz zapora sieciowa dla każdego identyfikatora UID, która blokuje aplikacjom dostęp do sieci w zależności od stanu telefonu. Statystyki zbierane przez to narzędzie są przechowywane w strukturze danych jądra o nazwie eBPF maps, a 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. Prace rozwojowe są prowadzone w ramach 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 platformie są też dostępne w framework/base/ i system/core.
Implementacja
Począwszy od Androida 9, urządzenia z Androidem z jądrem 4.9 lub nowszym, które zostały pierwotnie dostarczone z Androidem P, MUSZĄ używać rozliczania monitorowania ruchu sieciowego opartego na eBPF zamiast xt_qtaguid. Nowa infrastruktura jest bardziej elastyczna i łatwiejsza w utrzymaniu oraz nie wymaga żadnego kodu jądra poza drzewem.
Główne różnice w konstrukcji między starszym a eBPF-owym monitorowaniem ruchu przedstawiono na rysunku 1.
Rysunek 1. Różnice w architekturze starszego (po lewej) i eBPF (po prawej) monitorowania ruchu
Nowa trafficController architektura opiera się na filtrze cgroup eBPF oraz xt_bpf module netfilter w jądrze. Te filtry eBPF są stosowane do pakietów wysyłanych i odbieranych, gdy przechodzą przez filtr. cgroupFiltr eBPF znajduje się w warstwie transportowej i odpowiada za zliczanie ruchu w odniesieniu do odpowiedniego identyfikatora UID w zależności od identyfikatora UID gniazda oraz ustawień przestrzeni użytkownika.
Filtr sieciowy xt_bpf jest podłączony do łańcuchów bw_raw_PREROUTING i bw_mangle_POSTROUTING i odpowiada za zliczanie ruchu na odpowiednim interfejsie.
Podczas uruchamiania procesu przestrzeni użytkownika trafficController tworzone są mapy eBPF
używane do zbierania danych, a wszystkie mapy są przypinane jako plik wirtualny w lokalizacji sys/fs/bpf.
Następnie uprzywilejowany proces bpfloader wczytuje wstępnie skompilowany program eBPF do jądra i dołącza go do odpowiedniego cgroup. W przypadku całego ruchu jest jeden węzeł główny cgroup, więc domyślnie wszystkie procesy powinny być w nim uwzględnione.cgroup
W czasie działania trafficController może oznaczać gniazdo tagiem lub usuwać tag, zapisując dane w polach traffic_cookie_tag_map i traffic_uid_counterSet_map. Usługa 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 trafficController i cgroup eBPF odpowiada też za blokowanie ruchu z określonych identyfikatorów UID w zależności od ustawień telefonu. Funkcja blokowania ruchu sieciowego na podstawie identyfikatora 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 funkcje TrafficController i NetworkStatsService będą działać zarówno w przypadku starszej, jak i nowej implementacji. Jeśli aplikacja korzysta z publicznych interfejsów API, nie powinna odczuwać żadnej różnicy, niezależnie od tego, 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 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 lub nowszym), do wdrożenia nowego narzędzia eBPF nie są wymagane żadne modyfikacje HAL-i, sterowników ani kodu jądra.
Wymagania
W konfiguracji jądra MUSZĄ być włączone te ustawienia:
CONFIG_CGROUP_BPF=yCONFIG_BPF=yCONFIG_BPF_SYSCALL=yCONFIG_NETFILTER_XT_MATCH_BPF=yCONFIG_INET_UDP_DIAG=y
Test konfiguracji jądra VTS pomaga sprawdzić, czy włączona jest prawidłowa konfiguracja.
Proces wycofywania starszego parametru xt_qtaguid
Nowe narzędzie eBPF zastępuje modułxt_qtaguid i modułxt_owner, na którym jest oparte. 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 proc modułu 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ł, aby uzyskać statystyki wykorzystania sieci przez każdą aplikację. Aplikacje z pakietem SDK na poziomie 28 lub wyższym nie mają dostępu do plików xt_qtaguid proc ze względu na zasady sepolicy.
W kolejnej wersji Androida po wersji 9 dostęp aplikacji do tych plików xt_qtaguid proc zostanie całkowicie zablokowany, a my zaczniemy usuwać moduł xt_qtaguid z nowych wspólnych jąder Androida. Po usunięciu 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 minimalna wersja jądra wymagana w przypadku wersji Androida będzie wynosić 4.9 lub więcej.
W przypadku Androida 9 tylko urządzenia, które są wprowadzane na rynek z Androidem 9, muszą mieć nową funkcję eBPF. W przypadku urządzeń, które zostały dostarczone z jądrem obsługującym narzędzia eBPF, zalecamy zaktualizowanie go do nowej funkcji eBPF podczas uaktualniania do Androida 9. Nie ma testu CTS, który wymuszałby tę aktualizację.
Weryfikacja
Regularnie pobieraj poprawki z wspólnych jąder Androida i głównej gałęzi AOSP Androida. Upewnij się, że Twoja implementacja przechodzi odpowiednie testy VTS i CTS, netd_unit_test oraz libbpf_test.
Testowanie
Istnieją testy jądra net_tests, które sprawdzają, czy masz włączone wymagane funkcje i czy masz przeniesione wstecz wymagane poprawki jądra. Testy są zintegrowane z testami VTS w wersji Androida 9. W folderach system/netd/(netd_unit_test i libbpf_test) znajdują się testy jednostkowe. W folderze netd_integration_test są testy, które sprawdzają ogólne działanie nowego narzędzia.
CTS i weryfikator CTS
Oba moduły monitorowania ruchu są obsługiwane w Androidzie 9, więc nie ma testu CTS, który wymuszałby wdrożenie nowego modułu na wszystkich urządzeniach. W przypadku urządzeń z jądrem w wersji nowszej niż 4.9, które pierwotnie były dostarczane z Androidem 9 (tzn. pierwszy poziom interfejsu API >= 28), istnieją testy CTS na GSI, które sprawdzają, czy nowy moduł jest prawidłowo skonfigurowany. Stare testy CTS, takie jak TrafficStatsTest, NetworkUsageStatsTest i CtsNativeNetTestCases, mogą służyć do weryfikacji zachowania pod kątem zgodności ze starym modułem UID.
Testy ręczne
W system/netd/ znajdują się testy jednostkowe (netd_unit_test, netd_integration_test i libbpf_test).
Dostępna jest funkcja dumpsys, która umożliwia ręczne sprawdzanie stanu. Polecenie
dumpsys netd wyświetla podstawowy stan modułu trafficController i informację, czy eBPF jest prawidłowo włączony. Jeśli eBPF jest włączony, polecenie dumpsys netd trafficcontroller wyświetla szczegółową zawartość każdej mapy eBPF, w tym informacje o oznaczonych gniazdach, statystyki według tagu, identyfikator UID i interfejs oraz dopasowanie identyfikatora UID właściciela.
Lokalizacje testów
Testy CTS znajdują się w tym katalogu:
- https://android.googlesource.com/platform/cts/+/android16-qpr1-release/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
- https://android.googlesource.com/platform/cts/+/android16-qpr1-release/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
- https://android.googlesource.com/platform/system/netd/+/android16-qpr1-release/tests/bpf_base_test.cpp
Testy VTS znajdują się na stronie https://android.googlesource.com/kernel/tests/+/android16-qpr1-release/net/test/bpf_test.py.
Testy jednostkowe znajdują się w: