Monitoreo de tráfico eBPF

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.

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 de trafficController se basa en el filtro cgroup , así como en el módulo de filtro de red xt_bpf dentro del kernel. 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

  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 de VTS es útil cuando se verifica que la configuración correcta está activada.

  2. 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:

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: