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 de 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 fonte 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 versões mais recentes e foram originalmente enviados com a versão P PRECISAM usar
a contabilização do 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, além de não exigir
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 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 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 e da configuração do espaço do usuário.
O netfilter xt_bpf
é conectado às cadeias bw_raw_PREROUTING
e bw_mangle_POSTROUTING
e é responsável por contar o tráfego na interface correta.
Na 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. Há um único cgroup
raiz para todo o tráfego. Portanto, todo o processo precisa ser incluído nesse cgroup
por padrão.
No tempo de execução, o trafficController
pode adicionar/remover uma tag de um soquete gravando no
traffic_cookie_tag_map
e no 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 é responsável 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
substitui o módulo xt_owner
no 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 legada do módulo xt_qtaguid
. Assim, TrafficController
e NetworkStatsService
serão executados com a implementação legada ou nova. Se o app 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 mais recente), não será necessário fazer modificações em HALs, drivers ou código do kernel para implementar a nova ferramenta eBPF.
Requisitos
A configuração do kernel PRECISA ter estas opçõ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 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 removendo o módulo xt_qtaguid
do kernel do Android e desativando as configurações desnecessárias.
No lançamento 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 receber cada estatística de uso da rede do app. Os apps com nível 28 do SDK
e mais recentes não podem acessar arquivos proc xt_qtaguid
pela 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 da remoção, vamos atualizar a configuração básica do Android para essa versão do kernel e desativar explicitamente o módulo xt_qtaguid
. O módulo xt_qtaguid
será totalmente descontinuado quando o requisito mínimo de versão do kernel para um lançamento do Android for 4.9 ou superior.
No Android 9, apenas os dispositivos lançados com essa versão precisam ter o novo recurso eBPF. Para dispositivos enviados com um kernel que pode oferecer suporte a ferramentas eBPF, recomendamos atualizar para o novo recurso eBPF ao fazer upgrade para o Android 9. Não há teste do CTS para forçar essa atualização.
Validação
Você precisa receber patches regularmente dos kernels comuns do Android e da
ramificação principal do AOSP do Android. Verifique se a implementação passa nos testes aplicáveis de VTS e CTS, no
netd_unit_test
e no libbpf_test
.
Teste
Há kernel net_tests para garantir que os recursos necessários estejam ativados e que os patches de kernel necessários tenham sido portados para versões anteriores. 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á um teste do 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 foram lançados originalmente com o Android 9 (ou seja,
o primeiro nível da API >= 28), há testes do 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 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
vai mostrar o conteúdo detalhado de cada mapa
eBPF, incluindo informações de soquete marcadas, estatísticas por tag, UID e iface, além de
correspondência de UID do proprietário.
Locais de teste
Os testes do CTS estão localizados em:
- https://android.googlesource.com/platform/cts/+/android16-release/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
- https://android.googlesource.com/platform/cts/+/android16-release/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
- https://android.googlesource.com/platform/system/netd/+/android16-release/tests/bpf_base_test.cpp
Os testes do VTS estão localizados em https://android.googlesource.com/kernel/tests/+/android16-release/net/test/bpf_test.py.
Os testes de unidade estão localizados em: