monitoreo de tráfico eBPF

La herramienta de tráfico de red eBPF utiliza una combinación de implementación de kernel y espacio de usuario para monitorear el uso de la red en el dispositivo desde el último inicio del dispositivo. Proporciona funciones adicionales, como etiquetado de sockets, separación del tráfico en primer plano y en segundo plano y firewall por UID para bloquear el acceso a la red de aplicaciones según el estado del teléfono. Las estadísticas recopiladas por la herramienta se almacenan en una estructura de datos del kernel llamada eBPF maps y servicios como NetworkStatsService utilizan el resultado 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 necesarios en el marco se encuentran también 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 originalmente se enviaron con la versión P DEBEN usar contabilidad de monitoreo de tráfico de red basada en eBPF en lugar de xt_qtaguid . La nueva infraestructura es más flexible y más fácil de mantener y no requiere ningún código de kernel fuera del árbol.

Las principales diferencias de diseño entre el monitoreo de tráfico heredado y eBPF se ilustran en la Figura 1.

Diferencias de diseño de monitoreo de tráfico heredado y eBPF

Figura 1. Diferencias en el diseño de monitoreo de tráfico heredado (izquierda) y eBPF (derecha)

El nuevo diseño trafficController se basa en el filtro eBPF per- cgroup así como en el módulo netfilter xt_bpf dentro del kernel. Estos filtros eBPF se aplican en el paquete tx/rx cuando pasan a través del filtro. El filtro cgroup eBPF 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 red xt_bpf está conectado a las cadenas 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 fija 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 único cgroup raíz 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 trafficController y cgroup eBPF 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 de detalle 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 nueva. Si la aplicación utiliza API públicas, no debería experimentar ninguna diferencia si se utilizan 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 los HAL, los controladores o el código del kernel para implementar la nueva herramienta eBPF.

Requisitos

  1. La configuración del kernel DEBE tener activadas las siguientes configuraciones:

    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

    La prueba de configuración del kernel VTS es útil para verificar que esté activada la configuración correcta.

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 de proceso del módulo xt_qtaguid se mueven al servicio NetworkManagement . Dependiendo de la versión del kernel del dispositivo y el primer nivel de API, el servicio NetworkManagement sabe si las herramientas eBPF están activadas y elige el módulo correcto para obtener la estadística de uso de la red de cada aplicación. Las aplicaciones con SDK de nivel 28 y superior no pueden acceder a los archivos proc xt_qtaguid mediante sepolicy.

En la próxima versión de Android posterior a 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. Una vez eliminado, 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 envían con un kernel que admite herramientas eBPF, recomendamos actualizarlo a la nueva función eBPF al actualizar a la versión Android 9. No existe ninguna prueba CTS para aplicar esa actualización.

Validación

Debes actualizar periódicamente los kernels comunes de Android y el AOSP principal de Android. Asegúrese de que su implementación pase las pruebas VTS y CTS aplicables, netd_unit_test y libbpf_test .

Pruebas

Hay net_tests del kernel para garantizar que tenga activadas las funciones requeridas y que los parches del kernel requeridos estén respaldados. Las pruebas están integradas como parte de las pruebas VTS de la versión de 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 del kernel superior a 4.9 que originalmente se envían con la versión 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. Se pueden utilizar pruebas CTS antiguas como TrafficStatsTest , NetworkUsageStatsTest y CtsNativeNetTestCases 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 ). Existe soporte de dumpsys para verificar manualmente el estado. El comando dumpsys netd muestra el estado básico del módulo trafficController y si eBPF está activado correctamente. Si eBPF está activado, el comando dumpsys netd trafficcontroller muestra el contenido detallado de cada mapa de eBPF, incluida información de socket etiquetado, estadísticas por etiqueta, UID e iface, y coincidencia de UID del propietario.

Lugares de prueba

Las pruebas CTS se encuentran en:

Las pruebas VTS se encuentran en https://android.googlesource.com/kernel/tests/+/main/net/test/bpf_test.py .

Las pruebas unitarias se encuentran en: