Monitoramento de tráfego eBPF

A ferramenta de tráfego de rede eBPF usa uma combinação de implementação de kernel e 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 de primeiro/segundo plano e firewall por UID para bloquear o acesso de aplicativos à rede, dependendo do estado do telefone. As estatísticas coletadas pela 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 ocorrem 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 necessárias na estrutura também estão na framework/base/ e system/core .

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 de fácil manutenção e não requer nenhum código de kernel fora da árvore.

As principais diferenças de projeto 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 design de monitoramento de tráfego legado (esquerda) e eBPF (direita)

O novo design trafficController é baseado no filtro cgroup eBPF, bem como no módulo xt_bpf netfilter dentro do kernel. Esses filtros eBPF são aplicados no pacote tx/rx quando eles 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 do 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 em 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 filtro 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 detalhado 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 herdada do módulo xt_qtaguid para que TrafficController e NetworkStatsService sejam executados com a implementação herdada ou nova. Se o aplicativo usar APIs públicas, não deverá haver nenhuma 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.

Processo de descontinuação legado do xt_qtaguid

A nova ferramenta eBPF está substituindo o módulo xt_qtaguid e o módulo xt_owner no qual 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 está 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 NetworkManagement Service. Dependendo da versão do kernel do dispositivo e do primeiro nível da 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 pela sepolicy.

Na próxima versão do Android após 9, o acesso do aplicativo a esses arquivos proc xt_qtaguid será completamente bloqueado e começaremos a remover o módulo xt_qtaguid dos novos kernels comuns do Android. Depois de removido, atualizaremos a configuração base 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 lançados com a versão Android 9 são obrigados a 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 regularmente patches dos kernels comuns do Android e do Android AOSP principal. Certifique-se de que sua implementação passe nos testes VTS e CTS aplicáveis, no netd_unit_test e no libbpf_test .

Teste

Existem net_tests de kernel para garantir que você tenha os recursos necessários ativados e os patches de kernel necessários sejam portados. 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.

CTS e verificador CTS

Como ambos os módulos de monitoramento de tráfego são compatíveis com a 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 de kernel superior a 4.9 que vêm originalmente 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.

Teste manual

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/+/main/net/test/bpf_test.py .

Os testes unitários estão localizados em: