La herramienta de tráfico de red de eBPF usa una combinación de implementación de espacio del usuario y kernel para supervisar el uso de red en el dispositivo desde el último inicio del dispositivo. Proporciona funcionalidades adicionales, como etiquetado de socket, separación de tráfico en primer plano y en segundo plano, y firewall por UID para bloquear apps y que no accedan a la red según el estado del teléfono. Las estadísticas recopiladas de la herramienta se almacenan en una estructura de datos del kernel llamada eBPF maps
, y el resultado es utilizado por servicios como NetworkStatsService
para proporcionar estadísticas de tráfico persistentes desde el último inicio.
Ejemplos y fuente
Los cambios en el espacio de usuario se encuentran principalmente en los proyectos system/netd
y framework/base
. El desarrollo se realiza en AOSP, por lo que el código de AOSP siempre estará actualizado. La fuente se encuentra principalmente en system/netd/server/TrafficController*
, system/netd/bpfloader
y system/netd/libbpf/
.
Algunos cambios de framework necesarios también se encuentran en framework/base/
y system/core
.
Implementación
A partir de Android 9, los dispositivos Android que se ejecutan en el kernel 4.9 o versiones posteriores y que originalmente se enviaron con la versión P DEBEN usar la contabilidad de supervisión de tráfico de red basada en eBPF en lugar de xt_qtaguid
. La
nueva infraestructura es más flexible y fácil de mantener, y no requiere
código de kernel fuera del árbol.
En la Figura 1, se ilustran las principales diferencias de diseño entre la supervisión de tráfico heredado y la de eBPF.
Figura 1: Diferencias de diseño entre el control de tráfico heredado (izquierda) y eBPF (derecha)
El nuevo diseño de trafficController
se basa en un filtro de eBPF por cgroup
y en el módulo netfilter xt_bpf
dentro del kernel. Estos filtros de eBPF se aplican en la transmisión y recepción de paquetes cuando pasan por el filtro. El filtro eBPF cgroup
se encuentra en la capa de transporte y es responsable de contar el tráfico en función del UID correcto según el UID del socket y la configuración del espacio de usuario.
El netfilter xt_bpf
está conectado a la cadena bw_raw_PREROUTING
y bw_mangle_POSTROUTING
, y es responsable de registrar el tráfico en la interfaz correcta.
En el momento del inicio, el proceso del espacio de usuario trafficController
crea los mapas de eBPF que se usan para la recopilación de datos y fija todos los mapas como un archivo virtual en sys/fs/bpf
.
Luego, el proceso con privilegios bpfloader
carga el programa eBPF precompilado en el kernel y lo adjunta al cgroup
correcto. Existe una única raíz cgroup
para todo el tráfico, por lo que todo el proceso debe incluirse en ese cgroup
de forma predeterminada.
Durante el tiempo de ejecución, trafficController
puede etiquetar o des etiquetar un socket escribiendo en traffic_cookie_tag_map
y traffic_uid_counterSet_map
. NetworkStatsService
puede leer los datos de estadísticas de tráfico de traffic_tag_stats_map
, traffic_uid_stats_map
y traffic_iface_stats_map
.
Además de la función de recopilación de estadísticas de tráfico, el filtro eBPF trafficController
y cgroup
también es responsable de bloquear el tráfico de ciertos UID según la configuración del teléfono. La función de bloqueo de tráfico de red basada en UID es un reemplazo del módulo xt_owner
dentro del kernel, y el modo de detalles se puede configurar escribiendo en traffic_powersave_uid_map
, traffic_standby_uid_map
y traffic_dozable_uid_map
.
La nueva implementación sigue la implementación del módulo xt_qtaguid
heredado, por lo que TrafficController
y NetworkStatsService
se ejecutarán con la implementación heredada o la nueva. Si la app usa APIs públicas, no debería experimentar ninguna diferencia si se usan herramientas de xt_qtaguid
o eBPF en segundo plano.
Si el kernel del dispositivo se basa en el kernel común de Android 4.9 (SHA39c856663dcc81739e52b02b77d6af259eb838f6 o versiones posteriores), no se requieren modificaciones en las HAL, los controladores ni el código del kernel para implementar la nueva herramienta eBPF.
Requisitos
La configuración del kernel DEBE tener activadas las siguientes opciones:
CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_INET_UDP_DIAG=y
La prueba de configuración del kernel de VTS es útil para verificar que se haya activado la configuración correcta.
Proceso de baja del atributo heredado xt_qtaguid
La nueva herramienta eBPF reemplazará los módulos xt_qtaguid
y xt_owner
en los que se basa. Comenzaremos a quitar el módulo xt_qtaguid
del kernel de Android y a inhabilitar sus parámetros de configuración innecesarios.
En la versión de Android 9, el módulo xt_qtaguid
se activa en todos los dispositivos, pero todas las APIs públicas que leen directamente el archivo proc del módulo xt_qtaguid
se mueven al servicio NetworkManagement
.
Según la versión del kernel del dispositivo y el primer nivel de API, el servicio NetworkManagement
sabe si las herramientas de eBPF están activadas y elige el módulo correcto para obtener cada estadística de uso de red de la app. Sepolicy bloquea el acceso de las apps con el nivel de SDK 28 y versiones posteriores a los archivos proc de xt_qtaguid
.
En la próxima versión de Android después de la 9, el acceso de las apps a esos archivos de proc xt_qtaguid
se bloqueará por completo. Comenzaremos a quitar el módulo xt_qtaguid
de los nuevos kernels comunes de Android. Después de quitarlo, actualizaremos la configuración base de Android para esa versión del kernel para desactivar el módulo xt_qtaguid
de forma explícita. El módulo xt_qtaguid
dejará de estar disponible por completo cuando el requisito de versión mínima del kernel para una versión de Android sea 4.9 o superior.
En la versión de Android 9, solo los dispositivos que se inician con la versión de Android 9 deben tener la nueva función de eBPF. En el caso de los dispositivos que se enviaron con un kernel que puede admitir herramientas de eBPF, te recomendamos que lo actualices a la nueva función de eBPF cuando realices la actualización a la versión de Android 9. No hay una prueba de CTS para aplicar esa actualización.
Validación
Debes tomar parches de los kernels comunes de Android y de la versión principal de AOSP de Android con regularidad. Asegúrate de que tu implementación pase las pruebas de VTS y CTS correspondientes, netd_unit_test
y libbpf_test
.
Prueba
Hay net_tests del kernel para garantizar que tengas las funciones requeridas activadas y los parches del kernel necesarios con portabilidad a versiones anteriores. Las pruebas se integran como parte de las pruebas de VTS de la versión de Android 9. Hay algunas pruebas de unidades en system/netd/
(netd_unit_test
y libbpf_test
). Hay algunas pruebas en netd_integration_test
para validar el comportamiento general de la nueva herramienta.
CTS y verificador de CTS
Como ambos módulos de supervisión de tráfico son compatibles con la versión de Android 9, no hay una prueba de CTS para forzar la implementación del módulo nuevo en todos los dispositivos. Sin embargo, en el caso de los dispositivos con una versión de kernel superior a 4.9 que se envían originalmente con la versión de Android 9 (es decir, el primer nivel de API >= 28), hay pruebas de CTS en GSI para validar que el nuevo módulo esté configurado correctamente. Las pruebas de CTS anteriores, como TrafficStatsTest
, NetworkUsageStatsTest
y CtsNativeNetTestCases
, se pueden usar para verificar que el comportamiento sea coherente con el módulo de UID anterior.
Pruebas manuales
Hay algunas pruebas de unidades en system/netd/
(netd_unit_test
,
netd_integration_test
y
libbpf_test
).
Hay compatibilidad con dumpsys para verificar el estado de forma manual. El comando dumpsys netd
muestra el estado básico del módulo trafficController
y si eBPF se activó correctamente. Si eBPF está activado, el comando dumpsys netd trafficcontroller
muestra el contenido detallado de cada mapa de eBPF, incluida la información de los sockets etiquetados, las estadísticas por etiqueta, el UID y la interfaz, y la coincidencia del UID del propietario.
Ubicaciones de prueba
Las pruebas de CTS se encuentran en los siguientes lugares:
- 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
Las pruebas de VTS se encuentran en https://android.googlesource.com/kernel/tests/+/main/net/test/bpf_test.py.
Las pruebas de unidades se encuentran en: