Monitorowanie ruchu eBPF

Narzędzie ruchu sieciowego eBPF wykorzystuje kombinację implementacji jądra i przestrzeni użytkownika do monitorowania wykorzystania sieci na urządzeniu od ostatniego uruchomienia urządzenia. Zapewnia dodatkowe funkcje, takie jak tagowanie gniazd, oddzielanie ruchu na pierwszym planie od tła i zapora sieciowa dla poszczególnych UID, aby blokować aplikacjom dostęp do sieci w zależności od stanu telefonu. Statystyki zebrane za pomocą narzędzia są przechowywane w strukturze danych jądra zwanej eBPF maps , a wyniki są wykorzystywane przez usługi takie jak NetworkStatsService w celu zapewnienia 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 . Rozwój odbywa się w AOSP, więc kod AOSP będzie zawsze aktualny. Źródła znajdują się głównie w system/netd/server/TrafficController* , system/netd/bpfloader i system/netd/libbpf/ . Niektóre niezbędne zmiany frameworka dotyczą również framework/base/ i system/core .

Realizacja

Począwszy od Androida 9, urządzenia z Androidem działające na jądrze 4.9 lub nowszym i oryginalnie dostarczane z wersją 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 spoza drzewa.

Główne różnice projektowe pomiędzy monitorowaniem ruchu w starszej wersji a monitorowaniem ruchu eBPF przedstawiono na rysunku 1.

Różnice w projektowaniu monitorowania ruchu w starszych wersjach i eBPF

Rysunek 1. Różnice w projektowaniu monitorowania ruchu w starszych wersjach (po lewej) i eBPF (po prawej).

Nowy projekt trafficController opiera się na filtrze eBPF per- cgroup oraz module xt_bpf netfilter wewnątrz jądra. Te filtry eBPF są nakładane na pakiet tx/rx, gdy przechodzą przez filtr. Filtr eBPF cgroup znajduje się w warstwie transportowej i odpowiada za zliczanie ruchu względem odpowiedniego UID w zależności od UID gniazda i ustawień przestrzeni użytkownika. Filtr sieciowy xt_bpf jest podłączony do łańcucha bw_raw_PREROUTING i bw_mangle_POSTROUTING i jest odpowiedzialny za zliczanie ruchu na właściwym interfejsie.

W czasie rozruchu proces trafficController w przestrzeni użytkownika tworzy mapy eBPF używane do gromadzenia danych i przypina wszystkie mapy jako plik wirtualny do sys/fs/bpf . Następnie uprzywilejowany proces bpfloader ładuje prekompilowany program eBPF do jądra i dołącza go do właściwej cgroup . Istnieje jedna główna cgroup dla całego ruchu, więc cały proces powinien być domyślnie zawarty w tej cgroup .

W czasie wykonywania trafficController ruchu może oznaczyć/odznaczyć gniazdo, zapisując w plikach traffic_cookie_tag_map i traffic_uid_counterSet_map . NetworkStatsService może odczytywać dane statystyczne o ruchu z traffic_tag_stats_map , traffic_uid_stats_map i traffic_iface_stats_map . Oprócz funkcji zbierania statystyk ruchu, trafficController i filtr cgroup eBPF odpowiadają również za blokowanie ruchu z określonych UID w zależności od ustawień telefonu. Funkcja blokowania ruchu sieciowego oparta na UID zastępuje moduł xt_owner wewnątrz jądra, a tryb szczegółowy można skonfigurować, pisząc do 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 TrafficController i NetworkStatsService będą działać zarówno ze starszą, jak i nową implementacją. Jeśli aplikacja korzysta z publicznych interfejsów API, nie powinno być żadnej różnicy, czy w tle używane są 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, sterowników ani kodu jądra.

Wymagania

  1. Konfiguracja jądra MUSI mieć włączone następujące konfiguracje:

    1. CONFIG_CGROUP_BPF=y
    2. CONFIG_BPF=y
    3. CONFIG_BPF_SYSCALL=y
    4. CONFIG_NETFILTER_XT_MATCH_BPF=y
    5. CONFIG_INET_UDP_DIAG=y

    Test konfiguracji jądra VTS jest pomocny przy sprawdzaniu, czy włączona jest poprawna konfiguracja.

Proces wycofywania starszej wersji xt_qtaguid

Nowe narzędzie eBPF zastępuje moduł xt_qtaguid oraz 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 , zostały przeniesione do usługi NetworkManagement Service. W zależności od wersji jądra urządzenia i pierwszego poziomu API, NetworkManagement Service wie, czy narzędzia eBPF są włączone i wybiera odpowiedni moduł, aby uzyskać dla każdej aplikacji statystykę wykorzystania sieci. Aplikacje z poziomem SDK 28 i wyższym mają blokowany dostęp do plików proc xt_qtaguid przez sepolicy.

W następnej wersji Androida po 9, dostęp aplikacji do plików proc xt_qtaguid zostanie całkowicie zablokowany. Zaczniemy usuwać moduł xt_qtaguid z nowych wspólnych jąder Androida. Po jego usunięciu zaktualizujemy podstawową konfigurację Androida dla tej wersji jądra, aby jawnie wyłączyć moduł xt_qtaguid . Moduł xt_qtaguid będzie całkowicie przestarzały, jeśli minimalna wymagana wersja jądra dla wersji Androida będzie wynosić 4.9 lub nowsza.

W wersji Androida 9 tylko urządzenia uruchamiane z wersją Androida 9 muszą mieć nową funkcję eBPF. W przypadku urządzeń dostarczonych z jądrem obsługującym narzędzia eBPF zalecamy aktualizację do nowej funkcji eBPF podczas aktualizacji do wersji Androida 9. Nie ma testu CTS wymuszającego tę aktualizację.

Walidacja

Powinieneś regularnie pobierać łatki z popularnych jąder Androida i głównego Androida AOSP. Upewnij się, że Twoja implementacja pomyślnie przeszła odpowiednie testy VTS i CTS, netd_unit_test i libbpf_test .

Testowanie

Istnieją testy jądra net_tests , które pozwalają upewnić się, że masz włączone wymagane funkcje i przeniesione wymagane poprawki jądra. Testy są zintegrowane w ramach testów VTS wersji Androida 9. Istnieje kilka testów jednostkowych w system/netd/ ( netd_unit_test i libbpf_test ). W netd_integration_test znajduje się kilka testów sprawdzających ogólne zachowanie nowego narzędzia.

CTS i weryfikator CTS

Ponieważ oba moduły monitorowania ruchu są obsługiwane w wersji Androida 9, nie ma testu CTS wymuszającego wdrożenie nowego modułu na wszystkich urządzeniach. Jednak w przypadku urządzeń z wersją jądra wyższą niż 4.9, które oryginalnie były dostarczane z wersją Androida 9 (tzn. pierwszy poziom API >= 28), dostępne są testy CTS na GSI w celu sprawdzenia, czy nowy moduł jest poprawnie skonfigurowany. Stare testy CTS, takie jak TrafficStatsTest , NetworkUsageStatsTest i CtsNativeNetTestCases można wykorzystać do sprawdzenia, czy zachowanie jest spójne ze starym modułem UID.

Testowanie ręczne

Istnieje kilka testów jednostkowych w system/netd/ ( netd_unit_test , netd_integration_test i libbpf_test ). Istnieje obsługa dumpsys do ręcznego sprawdzania statusu. Komenda dumpsys netd pokazuje podstawowy stan modułu trafficController oraz to, czy eBPF jest poprawnie włączony. Jeśli eBPF jest włączone, polecenie dumpsys netd trafficcontroller wyświetla szczegółową zawartość każdej mapy eBPF, w tym informacje o oznakowanych gniazdach, statystyki poszczególnych znaczników, UID i iface oraz dopasowanie UID właściciela.

Lokalizacje testowe

Testy CTS znajdują się pod adresem:

Testy VTS znajdują się pod adresem https://android.googlesource.com/kernel/tests/+/main/net/test/bpf_test.py .

Testy jednostkowe znajdują się pod adresem: