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 aparelho. 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 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 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 estará sempre 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 foram enviados originalmente com a versão P precisam usar a contabilização 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 exige 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.
Figura 1. Diferenças de design de monitoramento de tráfego legado (à esquerda) e eBPF (à direita)
O novo design trafficController é baseado no filtro eBPF por cgroup, bem como no módulo de netfilter xt_bpf dentro do kernel. Esses filtros eBPF são aplicados no tx/rx de pacotes quando eles passam pelo filtro. O filtro eBPF cgroup está localizado na camada de transporte e é responsável por contabilizar o tráfego em relação ao UID correto, dependendo do UID do soquete e da configuração do espaço do usuário.
O netfilter xt_bpf é conectado à cadeia bw_raw_PREROUTING e bw_mangle_POSTROUTING e é responsável por contabilizar 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. Há um único cgroup raiz para todo o tráfego, então todos os processos precisam ser incluídos nesse cgroup por padrão.
No momento da 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 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 baseado em UID é uma substituição do módulo xt_owner dentro do 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 do módulo xt_qtaguid legado, então TrafficController e NetworkStatsService serão executados com a implementação legada ou nova. Se o app usar APIs públicas, ele não vai apresentar nenhuma diferença, seja xt_qtaguid ou ferramentas eBPF 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
A configuração do kernel precisa ter estas configurações ativadas:
CONFIG_CGROUP_BPF=yCONFIG_BPF=yCONFIG_BPF_SYSCALL=yCONFIG_NETFILTER_XT_MATCH_BPF=yCONFIG_INET_UDP_DIAG=y
O teste de configuração do kernel VTS é útil ao verificar se a configuração correta está ativada.
Processo de suspensão de uso do xt_qtaguid legado
A nova ferramenta eBPF está substituindo o módulo xt_qtaguid e o módulo xt_owner em que ele 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 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 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 da rede do app. Os apps com o nível 28 do SDK e mais recentes são impedidos de acessar arquivos proc 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á completamente bloqueado. 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á totalmente suspenso 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 enviados com um kernel que possa oferecer suporte a ferramentas eBPF, recomendamos atualizá-lo para o novo recurso eBPF ao fazer upgrade para a versão do Android 9. Não há teste CTS para aplicar essa atualização.
Validação
É necessário receber patches regularmente dos kernels comuns do Android e do Android AOSP main. Verifique se a implementação passa nos testes VTS e CTS aplicáveis, no netd_unit_test e no libbpf_test.
Teste
Há
net_tests do kernel
para garantir que você tenha os recursos necessários ativados e os patches de kernel necessários
portados. 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 CTS para forçar a implementação do novo módulo em todos os dispositivos. No entanto, para dispositivos com versão do kernel mais recente que 4.9 que foram enviados originalmente com a versão do Android 9 (ou seja, o primeiro nível da API >= 28), há testes CTS na 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
Há alguns testes de unidade em system/netd/
(netd_unit_test,
netd_integration_test
e
libbpf_test).
Há suporte para 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 mostrará 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:
- https://android.googlesource.com/platform/cts/+/android17-release/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
- https://android.googlesource.com/platform/cts/+/android17-release/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
- https://android.googlesource.com/platform/system/netd/+/android17-release/tests/bpf_base_test.cpp
Os testes VTS estão localizados em https://android.googlesource.com/kernel/tests/+/android17-release/net/test/bpf_test.py.
Os testes de unidade estão localizados em: