Monitoramento de tráfego eBPF

A ferramenta de tráfego de rede eBPF usa uma combinação de kernel e implementação de espaço do usuário para monitorar o uso da rede no dispositivo desde a última inicialização do dispositivo. Ela oferece outras funcionalidades, como inclusão de tag em soquetes, separação de tráfego em primeiro e segundo plano e firewall por UID para impedir que apps acessem a rede, dependendo do estado do smartphone. As estatísticas coletadas da ferramenta são armazenadas em uma estrutura de dados do kernel chamada eBPF maps, e o resultado é usado por serviços como NetworkStatsService para fornecer estatísticas de tráfego persistentes desde a última inicialização.

Exemplos e origem

As mudanças no espaço do usuário estão principalmente nos projetos system/netd e framework/base. O desenvolvimento está sendo feito no AOSP, então o código do AOSP sempre estará atualizado. A origem está localizada principalmente em system/netd/server/TrafficController*, system/netd/bpfloader e system/netd/libbpf/. Algumas mudanças necessárias no framework também estão em framework/base/ e system/core.

Implementação

A partir do Android 9, os dispositivos Android que executam o kernel 4.9 ou mais recente e que foram enviados originalmente com a versão P PRECISAM usar a contabilidade de monitoramento de tráfego de rede baseada em eBPF em vez de xt_qtaguid. A nova infraestrutura é mais flexível e fácil de manter e não requer nenhum código de kernel fora da árvore.

As principais diferenças de design entre o monitoramento de tráfego legado e o eBPF são ilustradas na Figura 1.

Diferenças entre o design do monitoramento de tráfego legados e o eBPF

Figura 1. Diferenças no design do monitoramento de tráfego legado (à esquerda) e eBPF (à direita)

O novo design do trafficController é baseado no filtro eBPF por cgroup, bem como no módulo xt_bpf netfilter dentro do kernel. Esses filtros eBPF são aplicados na transmissão/recepção de pacotes quando eles passam pelo filtro. O filtro eBPF cgroup está localizado na camada de transporte e é responsável por contar o tráfego com o UID correto, dependendo do UID do soquete e da configuração do espaço do usuário. O Netfilter xt_bpf é conectado na cadeia bw_raw_PREROUTING e bw_mangle_POSTROUTING e é responsável por contar o tráfego na interface correta.

No momento da inicialização, o processo do espaço do usuário trafficController cria os mapas eBPF usados para a coleta de dados e fixa todos os mapas como um arquivo virtual em sys/fs/bpf. Em seguida, o processo privilegiado bpfloader carrega o programa eBPF pré-compilado no kernel e o anexa ao cgroup correto. Há um único cgroup raiz para todo o tráfego. Portanto, todo o processo precisa ser incluído nesse cgroup por padrão.

No momento da execução, o trafficController pode marcar/remover a marcação de um soquete escrevendo no traffic_cookie_tag_map e traffic_uid_counterSet_map. O NetworkStatsService pode ler os dados de estatísticas de tráfego de traffic_tag_stats_map, traffic_uid_stats_map e traffic_iface_stats_map. Além da função de coleta de estatísticas de tráfego, os filtros eBPF trafficController e cgroup também são responsáveis por bloquear o tráfego de determinados UIDs, dependendo das configurações do smartphone. O recurso de bloqueio de tráfego de rede com base no UID é uma substituição do módulo xt_owner no kernel, e o modo de detalhes pode ser configurado gravando em traffic_powersave_uid_map, traffic_standby_uid_map e traffic_dozable_uid_map.

A nova implementação segue a implementação legada do módulo xt_qtaguid. Portanto, TrafficController e NetworkStatsService serão executados com a implementação legada ou nova. Se o app usa APIs públicas, não haverá diferença se as ferramentas xt_qtaguid ou eBPF forem usadas em segundo plano.

Se o kernel do dispositivo for baseado no kernel comum do Android 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 ou mais recente), nenhuma modificação em HALs, drivers ou código do kernel será necessária para implementar a nova ferramenta eBPF.

Requisitos

  1. A configuração do kernel PRECISA ter as seguintes configurações ativadas:

    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

    O teste de configuração do kernel do VTS é útil para verificar se a configuração correta está ativada.

Processo de descontinuação do xt_qtaguid legado

A nova ferramenta eBPF está substituindo o módulo xt_qtaguid e o módulo xt_owner em que ela se baseia. Vamos começar a remover o módulo xt_qtaguid do kernel do Android e desativar as configurações desnecessárias.

Na versão do Android 9, o módulo xt_qtaguid é ativado em todos os dispositivos, mas todas as APIs públicas que leem diretamente o arquivo proc do módulo xt_qtaguid são movidas para o serviço NetworkManagement. Dependendo da versão do kernel do dispositivo e do primeiro nível da API, o serviço NetworkManagement sabe se as ferramentas eBPF estão ativadas e escolhe o módulo certo para cada estatística de uso de rede do app. Apps com o nível 28 do SDK e mais recentes são bloqueados para acessar arquivos de processo xt_qtaguid por sepolicy.

Na próxima versão do Android após a 9, o acesso do app a esses arquivos proc xt_qtaguid será totalmente bloqueado, e vamos começar a remover o módulo xt_qtaguid dos novos kernels comuns do Android. Depois que ele for removido, vamos atualizar a configuração de base do Android para essa versão do kernel para desativar explicitamente o módulo xt_qtaguid. O módulo xt_qtaguid será descontinuado completamente quando o requisito mínimo de versão do kernel para uma versão do Android for 4.9 ou mais recente.

Na versão do Android 9, apenas os dispositivos lançados com a versão do Android 9 precisam ter o novo recurso eBPF. Para dispositivos que foram enviados com um kernel que pode oferecer suporte a ferramentas eBPF, recomendamos atualizar para o novo recurso eBPF ao fazer upgrade para a versão do Android 9. Não há teste do CTS para aplicar essa atualização.

Validação

É necessário usar patches regularmente de kernels comuns do Android e do Android AOSP principal. Verifique se a implementação foi aprovada nos testes de VTS e CTS, netd_unit_test e libbpf_test aplicáveis.

Teste

kernel net_tests para garantir que os recursos necessários estejam ativados e que os patches do kernel necessários sejam enviados de volta. Os testes são integrados como parte dos testes VTS da versão do Android 9. Há alguns testes de unidade em system/netd/ (netd_unit_test e libbpf_test). Há alguns testes em netd_integration_test para validar o comportamento geral da nova ferramenta.

CTS e verificador do CTS

Como os dois módulos de monitoramento de tráfego são compatíveis com a versão do Android 9, não há teste de CTS para forçar a implementação do novo módulo em todos os dispositivos. No entanto, para dispositivos com versão do kernel superior a 4.9 que são enviados originalmente com a versão do Android 9 (ou seja, o primeiro nível de API >= 28), há testes de CTS na GSI para validar se o novo módulo está configurado corretamente. Testes antigos do CTS, como TrafficStatsTest, NetworkUsageStatsTest e CtsNativeNetTestCases, podem ser usados para verificar se o comportamento é consistente com o módulo UID antigo.

Teste manual

Há alguns testes de unidade em system/netd/ (netd_unit_test, netd_integration_test e libbpf_test). Há suporte a dumpsys para verificar o status manualmente. O comando dumpsys netd mostra o status básico do módulo trafficController e se o eBPF está ativado corretamente. Se o eBPF estiver ativado, o comando dumpsys netd trafficcontroller vai mostrar o conteúdo detalhado de cada mapa eBPF, incluindo informações de soquete marcadas, estatísticas por tag, UID e iface e correspondência de UID do proprietário.

Locais de teste

Os testes do CTS estão localizados em:

Os testes do VTS estão localizados em https://android.googlesource.com/kernel/tests/+/main/net/test/bpf_test.py.

Os testes de unidade estão localizados em: