La herramienta de tráfico de red eBPF utiliza una combinación de kernel e implementación de espacio de usuario para monitorear el uso de la red en el dispositivo desde el último arranque del dispositivo. Proporciona funciones adicionales, como el etiquetado de sockets, la separación del tráfico de primer plano/de fondo y el firewall por UID para bloquear el acceso de las aplicaciones 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 lo utilizan servicios como NetworkStatsService
para proporcionar estadísticas de tráfico persistentes desde el último arranque.
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 AOSP siempre estará actualizado. La fuente se encuentra principalmente en system/netd/server/TrafficController*
, system/netd/bpfloader
y system/netd/libbpf/
. Algunos cambios de marco 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 superior y que se enviaron originalmente con la versión P DEBEN usar la contabilidad de monitoreo 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 ningún código de núcleo fuera del árbol.
Las principales diferencias de diseño entre el monitoreo de tráfico heredado y eBPF se ilustran en la Figura 1.
Figura 1. Diferencias en el diseño de monitoreo de tráfico heredado (izquierda) y eBPF (derecha)
El nuevo diseño de trafficController
se basa en el filtro cgroup
, así como en el módulo de filtro de red xt_bpf
dentro del núcleo. Estos filtros eBPF se aplican sobre el paquete tx/rx cuando pasan por el filtro. El filtro cgroup
cgroup está ubicado en la capa de transporte y es responsable de contar el tráfico con el UID correcto según el UID del socket y la configuración del espacio de usuario. El filtro de xt_bpf
está enganchado en la cadena bw_raw_PREROUTING
y bw_mangle_POSTROUTING
y es responsable de contar el tráfico en la interfaz correcta.
En el momento del arranque, el proceso de espacio de usuario trafficController
crea los mapas eBPF utilizados para la recopilación de datos y ancla todos los mapas como un archivo virtual en sys/fs/bpf
. Luego, el proceso privilegiado bpfloader
carga el programa eBPF precompilado en el kernel y lo adjunta al cgroup
correcto. Hay un cgroup
raíz único para todo el tráfico, por lo que todo el proceso debe incluirse en ese cgroup
de forma predeterminada.
En tiempo de ejecución, trafficController
puede etiquetar/desetiquetar 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 cgroup
trafficController
también son responsables 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 detallado 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 heredado xt_qtaguid
, por lo que TrafficController
y NetworkStatsService
se ejecutarán con la implementación heredada o nueva. Si la aplicación usa API públicas, no debería experimentar ninguna diferencia si se usan las herramientas xt_qtaguid
o eBPF en segundo plano.
Si el kernel del dispositivo se basa en el kernel común de Android 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 o superior), no se requieren modificaciones en las HAL, los controladores o el código del kernel para implementar la nueva herramienta eBPF.
Requisitos
La configuración del kernel DEBE tener activadas las siguientes configuraciones:
-
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 cuando se verifica que la configuración correcta está activada.
-
El
MEM_LOCK
dispositivo DEBE establecerse en 8 MB o más.
Proceso de obsolescencia de xt_qtaguid heredado
La nueva herramienta eBPF reemplaza el módulo xt_qtaguid
y el módulo xt_owner
en el que se basa. Comenzaremos a eliminar el módulo xt_qtaguid
del kernel de Android y deshabilitaremos sus configuraciones innecesarias.
En la versión de Android 9, el módulo xt_qtaguid
está activado en todos los dispositivos, pero todas las API 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 la API, NetworkManagement
Service sabe si las herramientas eBPF están activadas y elige el módulo adecuado para cada estadística de uso de la red de la aplicación. xt_qtaguid
bloquea el acceso de las aplicaciones con SDK nivel 28 y superior para acceder a los archivos proc xt_qtaguid.
En la próxima versión de Android después de la 9, el acceso de la aplicación a esos archivos proc xt_qtaguid
se bloqueará por completo. Comenzaremos a eliminar el módulo xt_qtaguid
de los nuevos núcleos comunes de Android. Después de eliminarlo, actualizaremos la configuración base de Android para esa versión del kernel para desactivar explícitamente el módulo xt_qtaguid
. El módulo xt_qtaguid
quedará completamente obsoleto cuando el requisito mínimo de versión 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 eBPF. Para los dispositivos que se enviaron con un kernel que puede admitir herramientas eBPF, recomendamos actualizarlo a la nueva función eBPF al actualizar a la versión de Android 9. No hay una prueba CTS para hacer cumplir esa actualización.
Validación
Debe tomar parches regularmente de los núcleos comunes de Android y del maestro AOSP de Android. Asegúrese de que su implementación pase las pruebas VTS y CTS aplicables, netd_unit_test
y libbpf_test
.
Pruebas
Hay kernel net_tests para asegurarse de que tiene las funciones requeridas activadas y los parches necesarios del kernel respaldados. Las pruebas están integradas como parte de las pruebas VTS de la versión Android 9. Hay algunas pruebas unitarias 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.
Verificador CTS y CTS
Debido a que ambos módulos de monitoreo de tráfico son compatibles con la versión de Android 9, no existe una prueba CTS para forzar la implementación del nuevo módulo en todos los dispositivos. Pero para los dispositivos con una versión de kernel superior a la 4.9 que se envían originalmente con la versión de Android 9 (es decir, el primer nivel de API >= 28), existen pruebas CTS en GSI para validar que el nuevo módulo esté configurado correctamente. Las pruebas CTS antiguas como TrafficStatsTest
, NetworkUsageStatsTest
y CtsNativeNetTestCases
se pueden usar para verificar que el comportamiento sea coherente con el módulo UID antiguo.
Prueba manual
Hay algunas pruebas unitarias en system/netd/
( netd_unit_test
, netd_integration_test
y libbpf_test
). Hay soporte dumpsys para verificar manualmente el estado. El comando dumpsys netd
muestra el estado básico del módulo trafficController
y si eBPF está correctamente activado. Si eBPF está activado, el comando dumpsys netd trafficcontroller
muestra el contenido detallado de cada mapa de eBPF, incluida la información de sockets etiquetados, estadísticas por etiqueta, UID e iface, y coincidencia de UID de propietario.
Ubicaciones de prueba
Las pruebas CTS se encuentran en:
- https://android.googlesource.com/platform/cts/+/master/tests/tests/net/src/android/net/cts/TrafficStatsTest.java {: .externo}
- https://android.googlesource.com/platform/cts/+/master/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java {: .external}
- https://android.googlesource.com/platform/system/netd/+/master/tests/bpf_base_test.cpp {: .externo}
Las pruebas de VTS se encuentran en https://android.googlesource.com/kernel/tests/+/master/net/test/bpf_test.py .
Las pruebas unitarias se encuentran en: