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/w tle oraz zapora sieciowa dla poszczególnych UID, aby blokować dostęp aplikacji do sieci w zależności od stanu telefonu. Statystyki zebrane z narzędzia są przechowywane w strukturze danych jądra zwanej eBPF maps a wyniki są wykorzystywane przez usługi takie jak NetworkStatsService do dostarczania stał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ło znajduje 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 Android działające na jądrze 4.9 lub wyższym i oryginalnie dostarczane z wydaniem P MUSZĄ używać opartego na eBPF rozliczania monitorowania ruchu sieciowego 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 między monitorowaniem ruchu starszego i eBPF przedstawiono na rysunku 1.

Różnice konstrukcyjne w monitorowaniu ruchu starszego i eBPF

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

Nowy projekt trafficController oparty jest na cgroup oraz module xt_bpf netfilter wewnątrz jądra. Te filtry eBPF są nakładane na pakiet tx/rx, gdy przechodzą przez filtr. cgroup cgroup znajduje się w warstwie transportowej i odpowiada za zliczanie ruchu według właściwego UID w zależności od UID gniazda oraz ustawienia przestrzeni użytkownika. xt_bpf jest podpięty do łańcucha bw_raw_PREROUTING i bw_mangle_POSTROUTING i jest odpowiedzialny za zliczanie ruchu z poprawnym interfejsem.

W czasie rozruchu proces trafficController w przestrzeni użytkownika tworzy mapy eBPF używane do zbierania danych i przypina wszystkie mapy jako wirtualny plik w sys/fs/bpf . Następnie proces uprzywilejowany bpfloader ładuje prekompilowany program eBPF do jądra i dołącza go do odpowiedniej 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 może oznaczać/odznaczać gniazdo, pisząc do traffic_cookie_tag_map i traffic_uid_counterSet_map . NetworkStatsService może odczytywać statystyki 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 są również odpowiedzialne za blokowanie ruchu z niektórych UID w zależności od ustawień telefonu. Funkcja blokowania ruchu sieciowego oparta na UID jest zamiennikiem modułu 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ły ze starszą lub 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 systemu Android 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 lub nowszym), do wdrożenia nowego narzędzia eBPF nie są wymagane żadne modyfikacje warstw 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.

  2. Urządzenie MEM_LOCK rlimit MUSI być ustawione na 8 MB lub więcej.

Starszy proces wycofywania xt_qtaguid

Nowe narzędzie eBPF zastępuje moduł xt_qtaguid oraz moduł xt_owner , na którym 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 proc modułu xt_qtaguid , są przenoszone do usługi NetworkManagement Service. W zależności od wersji jądra urządzenia i pierwszego poziomu interfejsu API, NetworkManagement Service wie, czy narzędzia eBPF są włączone i wybiera odpowiedni moduł, aby uzyskać dla każdej statystyki użycia sieci aplikacji. Aplikacje z poziomem SDK 28 i wyższym są blokowane przed dostępem do plików proc xt_qtaguid przez sepolicy.

W następnej wersji Androida po 9, dostęp aplikacji do tych 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 zostanie całkowicie przestarzały, gdy minimalna wymagana wersja jądra dla wersji Androida to 4.9 lub nowsza.

W wersji Android 9 tylko urządzenia uruchamiane z wersją Android 9 muszą mieć nową funkcję eBPF. W przypadku urządzeń dostarczanych z jądrem, które obsługuje narzędzia eBPF, zalecamy aktualizację do nowej funkcji eBPF podczas aktualizacji do wersji Androida 9. Nie ma testu CTS, który wymusiłby tę aktualizację.

Walidacja

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

Testowanie

Istnieją testy net_tests jądra, które zapewniają, że masz włączone wymagane funkcje i przeniesione wymagane łaty jądra. Testy są zintegrowane w ramach testów VTS w wersji Android 9. Istnieje kilka testów jednostkowych w system/netd/ ( netd_unit_test i libbpf_test ). Istnieje kilka testów w netd_integration_test , aby sprawdzić ogólne zachowanie nowego narzędzia.

Weryfikator CTS i CTS

Ponieważ oba moduły monitorowania ruchu są obsługiwane w wersji Android 9, nie ma testu CTS, który wymusiłby wdrożenie nowego modułu na wszystkich urządzeniach. Jednak dla urządzeń z wersją jądra wyższą niż 4.9, które oryginalnie dostarczane jest z wydaniem Androida 9 (tj. pierwszy poziom API >= 28), istnieją testy CTS na GSI, aby sprawdzić, czy nowy moduł jest poprawnie 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.

Testowanie ręczne

Istnieje kilka testów jednostkowych w system/netd/ ( netd_unit_test , netd_integration_test i libbpf_test ). Dostępna jest obsługa dumpsys do ręcznego sprawdzania stanu. Polecenie dumpsys netd pokazuje podstawowy stan modułu trafficController i czy eBPF jest poprawnie włączony. Jeśli eBPF jest włączony, polecenie dumpsys netd trafficcontroller pokazuje szczegółową zawartość każdej mapy eBPF, w tym informacje o oznaczonych gniazdach, statystyki na tag, 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/+/master/net/test/bpf_test.py .

Testy jednostkowe znajdują się w: