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 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 envían originalmente con la versión P DEBEN usar la contabilización de supervisión del 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 el filtro eBPF por cgroup
, así como en el módulo netfilter xt_bpf
dentro del kernel. Estos filtros de eBPF se aplican a 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 contar 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. Hay una sola raíz cgroup
para todo el tráfico, por lo que todo el proceso debe incluirse en esa 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 implementación nueva 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 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 o versiones posteriores), no se requieren modificaciones en los HAL, los controladores ni el código del kernel para implementar la nueva herramienta de 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 cuando se verifica que la configuración correcta está activada.
Proceso de baja de xt_qtaguid heredado
La nueva herramienta de eBPF reemplaza el módulo xt_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 parámetros de configuración innecesarios.
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 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, y 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 necesarias activadas y los parches del kernel necesarios con portabilidad a versiones anteriores. Las pruebas se integran como parte de las pruebas de VTS de lanzamiento 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 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 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: