L'outil de trafic réseau eBPF utilise une combinaison d'implémentations du noyau et de l'espace utilisateur pour surveiller l'utilisation du réseau sur l'appareil depuis le dernier démarrage de l'appareil. Il fournit des fonctionnalités supplémentaires telles que l'ajout de tags de socket, qui sépare le trafic de premier plan/en arrière-plan et le pare-feu par UID pour empêcher les applications d'accéder au réseau en fonction de l'état du téléphone. Les statistiques collectées à partir de l'outil sont stockées dans une structure de données de kernel appelée eBPF maps
. Le résultat est utilisé par des services tels que NetworkStatsService
pour fournir des statistiques de trafic persistantes depuis le dernier démarrage.
Exemples et source
Les modifications apportées à l'espace utilisateur se trouvent principalement dans les projets system/netd
et framework/base
. Le développement est effectué dans AOSP. Le code AOSP est donc toujours à jour. La source se trouve principalement dans system/netd/server/TrafficController*
, system/netd/bpfloader
et system/netd/libbpf/
.
Certaines modifications de framework nécessaires se trouvent également dans framework/base/
et system/core
.
Implémentation
À partir d'Android 9, les appareils Android exécutant le kernel 4.9 ou version ultérieure et livrés à l'origine avec la version P DOIVENT utiliser la comptabilité de surveillance du trafic réseau basée sur eBPF au lieu de xt_qtaguid
. La nouvelle infrastructure est plus flexible et plus facile à gérer, et ne nécessite aucun code de noyau hors du noyau.
Les principales différences de conception entre l'ancienne surveillance du trafic et la surveillance du trafic eBPF sont illustrées dans la figure 1.
Figure 1 : Différences de conception entre l'ancienne version de la surveillance du trafic (à gauche) et celle de l'eBPF (à droite)
La nouvelle conception de trafficController
est basée sur un filtre eBPF par cgroup
, ainsi que sur le module netfilter xt_bpf
dans le noyau. Ces filtres eBPF sont appliqués aux paquets de transmission/réception lorsqu'ils passent par le filtre. Le filtre eBPF cgroup
se trouve au niveau de la couche transport et est chargé de comptabiliser le trafic avec le bon UID en fonction de l'UID du socket et du paramètre d'espace utilisateur.
Le netfilter xt_bpf
est connecté à la chaîne bw_raw_PREROUTING
et bw_mangle_POSTROUTING
, et est chargé de comptabiliser le trafic sur l'interface appropriée.
Au démarrage, le processus d'espace utilisateur trafficController
crée les cartes eBPF utilisées pour la collecte de données et épingle toutes les cartes en tant que fichier virtuel à sys/fs/bpf
.
Le processus privilégié bpfloader
charge ensuite le programme eBPF précompilé dans le noyau et l'associe au cgroup
approprié. Il existe un seul cgroup
racine pour tout le trafic. Par conséquent, tout le processus doit être inclus dans ce cgroup
par défaut.
Au moment de l'exécution, trafficController
peut ajouter/supprimer un tag à un socket en écrivant dans traffic_cookie_tag_map
et traffic_uid_counterSet_map
. NetworkStatsService
peut lire les données de statistiques sur le trafic à partir de traffic_tag_stats_map
, traffic_uid_stats_map
et traffic_iface_stats_map
.
En plus de la fonction de collecte des statistiques sur le trafic, le filtre eBPF trafficController
et cgroup
est également chargé de bloquer le trafic provenant de certains UID en fonction des paramètres du téléphone. La fonctionnalité de blocage du trafic réseau basée sur l'UID remplace le module xt_owner
dans le noyau. Le mode détaillé peut être configuré en écrivant dans traffic_powersave_uid_map
, traffic_standby_uid_map
et traffic_dozable_uid_map
.
La nouvelle implémentation suit l'ancienne implémentation du module xt_qtaguid
. TrafficController
et NetworkStatsService
s'exécutent donc avec l'ancienne ou la nouvelle implémentation. Si l'application utilise des API publiques, elle ne devrait pas constater de différence si des outils xt_qtaguid
ou eBPF sont utilisés en arrière-plan.
Si le noyau de l'appareil est basé sur le noyau commun Android 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 ou version ultérieure), aucune modification des HAL, des pilotes ou du code du noyau n'est requise pour implémenter le nouvel outil eBPF.
Conditions requises
Les configurations suivantes DOIVENT être activées dans la configuration du noyau:
CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_INET_UDP_DIAG=y
Le test de configuration du kernel VTS est utile pour vérifier que la configuration appropriée est activée.
Processus d'abandon de l'ancien xt_qtaguid
Le nouvel outil eBPF remplace le module xt_qtaguid
et le module xt_owner
sur lequel il est basé. Nous allons commencer par supprimer le module xt_qtaguid
du kernel Android et désactiver ses configurations inutiles.
Dans la version d'Android 9, le module xt_qtaguid
est activé sur tous les appareils, mais toutes les API publiques qui lisent directement le fichier proc du module xt_qtaguid
sont déplacées vers le service NetworkManagement
.
En fonction de la version du kernel de l'appareil et du premier niveau d'API, le service NetworkManagement
sait si les outils eBPF sont activés et choisit le bon module à obtenir pour chaque statistique d'utilisation du réseau de l'application. Les applications avec un niveau de SDK 28 ou supérieur sont empêchées d'accéder aux fichiers proc xt_qtaguid
par sepolicy.
Dans la prochaine version d'Android après la version 9, l'accès des applications à ces fichiers proc xt_qtaguid
sera complètement bloqué. Nous commencerons à supprimer le module xt_qtaguid
des nouveaux noyaux Android courants. Une fois le module supprimé, nous mettrons à jour la configuration de base Android pour cette version de kernel afin de désactiver explicitement le module xt_qtaguid
. Le module xt_qtaguid
sera complètement abandonné lorsque la version minimale de kernel requise pour une version d'Android sera 4.9 ou supérieure.
Dans la version Android 9, seuls les appareils lancés avec la version Android 9 doivent disposer de la nouvelle fonctionnalité eBPF. Pour les appareils livrés avec un noyau compatible avec les outils eBPF, nous vous recommandons de passer à la nouvelle fonctionnalité eBPF lors de la mise à niveau vers la version Android 9. Aucun test CTS n'est effectué pour appliquer cette mise à jour.
Validation
Vous devez régulièrement récupérer les correctifs des noyaux communs Android et du noyau principal Android AOSP. Assurez-vous que votre implémentation passe les tests VTS et CTS applicables, les netd_unit_test
et les libbpf_test
.
Tests
L'outil kernel net_tests permet de vérifier que les fonctionnalités requises sont activées et que les correctifs de noyau requis sont rétroportés. Les tests sont intégrés aux tests VTS de la version Android 9. Des tests unitaires sont disponibles dans system/netd/
(netd_unit_test
et libbpf_test
). netd_integration_test
permet de valider le comportement global du nouvel outil.
CTS et vérificateur CTS
Étant donné que les deux modules de surveillance du trafic sont compatibles avec la version Android 9, aucun test CTS n'est effectué pour forcer l'implémentation du nouveau module sur tous les appareils. Toutefois, pour les appareils dont la version du noyau est supérieure à 4.9 et qui sont initialement livrés avec la version Android 9 (c'est-à-dire le premier niveau d'API ≥ 28), des tests CTS sont effectués sur GSI pour valider que le nouveau module est correctement configuré. Les anciens tests CTS tels que TrafficStatsTest
, NetworkUsageStatsTest
et CtsNativeNetTestCases
peuvent être utilisés pour vérifier que le comportement est cohérent avec l'ancien module UID.
Tests manuels
Des tests unitaires sont disponibles dans system/netd/
(netd_unit_test
, netd_integration_test
et libbpf_test
). Dans dumpsys, il est possible de vérifier manuellement l'état. La commande dumpsys netd
affiche l'état de base du module trafficController
et si eBPF est correctement activé. Si eBPF est activé, la commande dumpsys netd trafficcontroller
affiche le contenu détaillé de chaque mappe eBPF, y compris les informations sur les sockets tagués, les statistiques par balise, l'UID et l'interface, ainsi que la correspondance de l'UID du propriétaire.
Emplacements des tests
Les tests CTS se trouvent à l'adresse suivante:
- 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 (en anglais)
Les tests VTS se trouvent sur https://android.googlesource.com/kernel/tests/+/main/net/test/bpf_test.py.
Les tests unitaires se trouvent à l'adresse:
- https://android.googlesource.com/platform/system/netd/+/main/libbpf/BpfNetworkStatsTest.cpp
- https://android.googlesource.com/platform/system/netd/+/main/server/TrafficControllerTest.cpp