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.
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
A configuração do kernel DEVE ter as seguintes configurações ativadas:
-
CONFIG_CGROUP_BPF=y
-
CONFIG_BPF=y
-
CONFIG_BPF_SYSCALL=y
-
CONFIG_NETFILTER_XT_MATCH_BPF=y
-
CONFIG_INET_UDP_DIAG=y
O teste de configuração do kernel VTS é útil ao verificar se a configuração correta está ativada.
-
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:
- https://android.googlesource.com/platform/cts/+/master/tests/tests/net/src/android/net/cts/TrafficStatsTest.java {: .external}
- https://android.googlesource.com/platform/cts/+/master/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java {: .external}
- https://android.googlesource.com/platform/system/netd/+/master/tests/bpf_base_test.cpp {: .external}
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: