Control de tráfico de eBPF

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 el acceso a la red de las apps 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 los servicios como NetworkStatsService usan el resultado para proporcionar estadísticas de tráfico persistentes desde el último inicio.

Ejemplos y fuente

Los cambios en el espacio del usuario se encuentran principalmente en los proyectos system/netd y framework/base. El desarrollo se realiza en el AOSP, por lo que el código del 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 framework también se encuentran en framework/base/ y system/core.

Implementación

A partir de Android 9, los dispositivos Android que ejecutan el kernel 4.9 o versiones posteriores y que se enviaron originalmente con la versión P DEBEN usar la contabilización del monitoreo del tráfico de red basado 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 del kernel fuera del árbol.

En la Figura 1, se ilustran las principales diferencias de diseño entre la supervisión de tráfico heredada y la basada en eBPF.

Diferencias de diseño entre el control de tráfico heredado y el de eBPF

Figura 1: Diferencias en el diseño del control de tráfico heredado (izquierda) y de eBPF (derecha)

El nuevo diseño de trafficController se basa en el filtro eBPF por cgroup y en el módulo xt_bpf netfilter dentro del kernel. Estos filtros eBPF se aplican a la transmisión y recepción de paquetes cuando pasan por el filtro. El filtro cgroup eBPF 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 del usuario. El xt_bpf netfilter se conecta 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 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. Hay un solo cgroup raíz para todo el tráfico, por lo que todos los procesos deben incluirse en ese cgroup de forma predeterminada.

En el tiempo de ejecución, el trafficController puede etiquetar o quitar la etiqueta de un socket escribiendo en traffic_cookie_tag_map y traffic_uid_counterSet_map. El 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 de eBPF también son responsables de bloquear el tráfico de ciertos UIDs según la configuración del teléfono. La función de bloqueo del tráfico de red basado en UID reemplaza el 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 heredada del módulo xt_qtaguid, 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 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 o posterior), no se requieren modificaciones en los HAL, los controladores ni el código del kernel para implementar la nueva herramienta de eBPF.

Requisitos

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

    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 para verificar que la configuración correcta esté activada.

Proceso de baja del parámetro xt_qtaguid heredado

La nueva herramienta eBPF reemplaza el móduloxt_qtaguid y el módulo xt_owner en el que se basa. Comenzaremos a quitar el módulo xt_qtaguid del kernel de Android y a inhabilitar sus configuraciones innecesarias.

En la versión de Android 9, el módulo xt_qtaguid está activado en todos los dispositivos, pero todas las APIs públicas que leen directamente el archivo proc del módulo xt_qtaguid se trasladan 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 adecuado para obtener cada estadística de uso de la red de la app. Se impide que las apps con el nivel de SDK 28 y versiones posteriores accedan a los archivos proc de xt_qtaguid por medio de sepolicy.

En la próxima versión de Android después de la 9, se bloqueará por completo el acceso de las apps a esos archivos xt_qtaguid proc y comenzaremos a quitar el módulo xt_qtaguid de los nuevos kernels comunes de Android. Después de que se quite, actualizaremos la configuración base de Android para esa versión del kernel y desactivaremos explícitamente el módulo xt_qtaguid. El módulo xt_qtaguid estará completamente desaprobado cuando el requisito de versión mínima del kernel para una versión de Android sea 4.9 o superior.

En el lanzamiento de Android 9, solo los dispositivos que se lanzan con Android 9 deben tener la nueva función de eBPF. En el caso de los dispositivos que se enviaron con un kernel que admite herramientas de eBPF, recomendamos actualizarlo a la nueva función de eBPF cuando se actualice a la versión de Android 9. No hay ninguna prueba del CTS para aplicar esa actualización.

Validación

Debes tomar parches de los kernels comunes de Android y de la rama principal de AOSP de Android con regularidad. Asegúrate de que tu implementación pase las pruebas de VTS y CTS aplicables, netd_unit_test y libbpf_test.

Prueba

Existen net_tests del kernel para garantizar que tengas activadas las funciones necesarias y que se hayan aplicado los parches del kernel necesarios. 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). También hay algunas pruebas en netd_integration_test para validar el comportamiento general de la nueva herramienta.

CTS y verificador de CTS

Dado que ambos módulos de supervisión del tráfico se admiten en la versión de Android 9, no hay ninguna prueba de CTS para forzar la implementación del nuevo módulo en todos los dispositivos. Sin embargo, para los dispositivos con una versión del 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 la GSI para validar que el nuevo módulo esté configurado correctamente. Se pueden usar pruebas de CTS anteriores, como TrafficStatsTest, NetworkUsageStatsTest y CtsNativeNetTestCases, 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). Se admite dumpsys para verificar el estado de forma manual. 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 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 las siguientes ubicaciones:

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

Las pruebas de unidades se encuentran en la siguiente ubicación: