Monitorowanie ruchu eBPF

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/bpfloadersystem/netd/libbpf/. Niektóre niezbędne zmiany w platformie są też dostępne w framework/base/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.

Różnice w projektowaniu starszego monitorowania ruchu i monitorowania ruchu eBPF

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_PREROUTINGbw_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_maptraffic_uid_counterSet_map. Usługa NetworkStatsService może odczytywać dane o statystykach ruchu z usług traffic_tag_stats_map, traffic_uid_stats_maptraffic_iface_stats_map. Oprócz funkcji zbierania statystyk ruchu filtr trafficControllercgroup 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_maptraffic_dozable_uid_map.

Nowa implementacja jest zgodna ze starszą implementacją modułu xt_qtaguid, więc funkcje TrafficControllerNetworkStatsService 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, sterowników ani kodu jądra.

Wymagania

  1. W konfiguracji jądra MUSZĄ być włączone te ustawienia:

    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 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 Androidzie 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. W zależności od wersji jądra urządzenia i pierwszego poziomu interfejsu API usługa NetworkManagementwie, 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_qtaguidproc ze względu na zasady bezpieczeństwa.

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_testlibbpf_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, NetworkUsageStatsTestCtsNativeNetTestCases, mogą służyć do weryfikacji zachowania pod kątem zgodności ze starym modułem UID.

Testy ręczne

system/netd/ znajdują się testy jednostkowe (netd_unit_test, netd_integration_testlibbpf_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:

Testy VTS znajdują się na stronie https://android.googlesource.com/kernel/tests/+/android16-release/net/test/bpf_test.py.

Testy jednostkowe znajdują się w: