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. Ele fornece funcionalidades adicionais, como marcação de soquete, separação de tráfego em primeiro plano/segundo plano e firewall por UID para bloquear aplicativos de acesso à rede, dependendo do estado do telefone. 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 fonte

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

Implementação

A partir do Android 9, os dispositivos Android executados no kernel 4.9 ou superior e originalmente fornecidos com a versão P DEVEM 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 mais 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 eBPF são ilustradas na Figura 1.

Diferenças de design de monitoramento de tráfego legado e eBPF

Figura 1. Diferenças de projeto de monitoramento de tráfego legado (esquerda) e eBPF (direita)

O novo design trafficController é baseado no filtro percgroup cgroup , bem como no módulo xt_bpf netfilter dentro do kernel. Esses filtros eBPF são aplicados no pacote tx/rx quando passam pelo filtro. O filtro cgroup eBPF está localizado na camada de transporte e é responsável por contar o tráfego em relação ao UID correto, dependendo do UID do soquete, bem como da configuração do espaço do usuário. O netfilter xt_bpf está conectado à 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 de espaço do usuário trafficController cria os mapas eBPF usados ​​para 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. Existe um único cgroup raiz para todo o tráfego, portanto, todo o processo deve ser incluído nesse cgroup por padrão.

Em tempo de execução, o trafficController pode marcar/desmarcar um soquete gravando 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, o trafficController e cgroup eBPF também são responsáveis ​​por bloquear o tráfego de determinados UIDs, dependendo das configurações do telefone. O recurso de bloqueio de tráfego de rede baseado em UID é uma substituição do módulo xt_owner dentro do kernel e o modo de detalhe 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 do módulo xt_qtaguid herdado para que TrafficController e NetworkStatsService sejam executados com a implementação herdada ou nova. Se o aplicativo usar 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 superior), nenhuma modificação nos HALs, drivers ou código do kernel será necessária para implementar a nova ferramenta eBPF.

Requisitos

  1. A configuração do kernel DEVE 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 VTS é útil ao verificar se a configuração correta está ativada.

  2. O dispositivo MEM_LOCK rlimit DEVE ser definido para 8 MB ou mais.

Processo de descontinuação de xt_qtaguid legado

A nova ferramenta eBPF está substituindo o módulo xt_qtaguid e o módulo xt_owner em que se baseia. Começaremos a remover o módulo xt_qtaguid do kernel do Android e desabilitar suas configurações desnecessárias.

Na versão Android 9, o módulo xt_qtaguid é ativado em todos os dispositivos, mas todas as APIs públicas que lêem diretamente o arquivo proc do módulo xt_qtaguid são movidas para o NetworkManagement Service. Dependendo da versão do kernel do dispositivo e do primeiro nível de API, o NetworkManagement Service sabe se as ferramentas eBPF estão ativadas e escolhe o módulo certo para obter para cada estatística de uso da rede do aplicativo. Aplicativos com SDK de nível 28 e superior são impedidos de acessar arquivos proc xt_qtaguid por sepolicy.

Na próxima versão do Android após 9, o acesso do aplicativo a esses arquivos xt_qtaguid proc será completamente bloqueado, começaremos a remover o módulo xt_qtaguid dos novos kernels comuns do Android. Depois que ele for removido, atualizaremos a configuração básica do Android para essa versão do kernel para desativar explicitamente o módulo xt_qtaguid . O módulo xt_qtaguid será completamente obsoleto quando o requisito mínimo de versão do kernel para uma versão do Android for 4.9 ou superior.

Na versão Android 9, apenas os dispositivos que são iniciados com a versão Android 9 precisam ter o novo recurso eBPF. Para dispositivos fornecidos com um kernel compatível com ferramentas eBPF, recomendamos atualizá-lo para o novo recurso eBPF ao atualizar para a versão Android 9. Não há teste CTS para impor essa atualização.

Validação

Você deve obter patches regularmente dos kernels comuns do Android e do Android AOSP master. Certifique-se de que sua implementação seja aprovada nos testes VTS e CTS aplicáveis, o netd_unit_test e o libbpf_test .

Teste

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

Verificador de CTS e CTS

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

Testes manuais

Existem alguns testes de unidade em system/netd/ ( netd_unit_test , netd_integration_test e libbpf_test ). Há suporte dumpsys para verificar manualmente o status. 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 mostra o conteúdo detalhado de cada mapa eBPF, incluindo informações de soquete marcado, estatísticas por tag, UID e iface e correspondência de UID do proprietário.

Locais de teste

Os testes CTS estão localizados em:

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

Os testes unitários estão localizados em: