2.5 FATORES QUE INFLUENCIAM O DESEMPENHO DA LIBPCAP
2.5.2 Otimizações de software (kernel e método de captura)
Apesar da libpcap implementar a mesma API em diferentes plataformas existe uma diferença entre estas com relação ao desempenho. Contudo, existem trabalhos em torno de três técnicas relacionadas à melhoria de desempenho e aproveitamento da captura passiva de pacotes baseada na API libpcap. Estas três técnicas são: device polling, NAPI (new API) e PF_RING. Cada uma destas técnicas serão descritas nesta seção como fatores ligados à melhoria de desempenho da biblioteca em estudo.
Dependendo do sistema operacional, a libpcap implementa um dispositivo virtual onde os pacotes são lidos de uma aplicação em espaço de usuário concorrendo com demais aplicações.[...] Em condições de pouco tráfego não existem diferenças entre as plataformas, no entanto, em ambientes de alta vazão de tráfego a situação muda significativamente (DERI, 2004, tradução).
Deri (2004) apresenta quadros comparativos em relação a captura de pacotes pela libpcap.
Uma dessas comparações pode ser vista na Tabela 1, no qual o ambiente de testes descrito é
baseado em computadores padrão de mercado13. Esta é uma comparação importante, pois em um mesmo ambiente percebe-se o baixo aproveitamento da captura de pacotes conseguido pela biblioteca.
Tabela 1: Percentual de captura de pacotes
Aplicação de captura de Tráfego Linux 2.4.x FreeBSD 4.8 Windows 2000
libpcap padrão 0,2% 34% 68%
libpcap mmap 1,0% - -
Módulo de Kernel (Netfilter) 4,0% - -
Fonte: Adaptado de Deri (2004)
Os resultados comparativos apresentados por Deri consistem no percentual de captura de pacotes em relação ao tráfego experimental gerado. Neste caso, libpcap padrão representa a implementação padrão da biblioteca, libpcap mmap uma versão especial da biblioteca que faz uso da chamada de sistema mmap() para passar os pacotes capturados para o espaço de usuário. Esta implementação difere da implementação padrão por permitir que regiões de memórias, neste caso utilizadas pelo Kernel, sejam mapeadas e utilizadas em espaço de usuário. A configuração Módulo de kernel implementa um módulo de kernel baseado no netfilter14. Este módulo difere da implementação padrão por fazer com que os pacotes sejam filtrados pelo próprio kernel. Ressalta-se que o experimento com esta opção representou uma melhoria significativa de performance mas com muitos pacotes perdidos o que mostra que maior parte do tempo ainda é perdido para mover os pacotes da placa de rede para o kernel e não do kernel para o espaço de usuário. Os resultados para Windows 2000 foram executados com a winpcap nos quais foram obtidos os melhores resultados (DERI, 2004). Esse resultado do MS Windows em comparação ao Linux e FreeBSD se dá pela otimização da Winpcap em termos de estrutura de armazenamento de pacotes em nível de kernel (DEGIOANNI et al, 2003). O baixo desempenho alcançado pelo sistema operacional linux se deu em função da utilização do kernel versão 2.4, o qual não contava com as otimizações promovidas pela NAPI, como device polling e reimplementação da API do sistema para manipulação dos dados da rede.
Deri (2004) afirma que o baixo desempenho da biblioteca demonstrado na Tabela 1 se deu em função de uma situação conhecida como livelock interrupt, onde em função da implementação
13 Gerador de pacotes: Dual 1.8 GHz Athlon, rede 3Com 3c59x. e VIA C3 533 MHz, rede Intel 100Mbit como cliente.
14 Informações sobre netfilter em: www.netfilter.org
do driver de dispositivo da placa de rede é gerada uma interrupção para o processador sempre que este dispositivo precisar de atenção. Em casos de tráfego elevado o sistema operacional gasta mais tempo com pedidos de interrupção do que atendendo outras tarefas. Com isso surge uma das melhorias voltadas ao desempenho da libpcap denominada device polling. Rizzo (2001, tradução) define device polling como “uma técnica para manipulação de dispositivos que não são confiáveis quanto aos pedidos de interrupção para utilização de CPU. [...] O modo polling trabalha fazendo com que o sistema operacional verifique periodicamente os dispositivos para verificar se estes precisam de atenção e invoca a manipulação de acordo com esta necessidade.” Isso faz com que o overhead causado pela troca de contexto diminua pois o sistema pode escolher em atender o dispositivo somente quando já estiver com o contexto correto, ou seja o tempo gasto para manipulação destes dispositivos podem se manter sob o controle do sistema operacional (RIZZO, 2001). Esta funcionalidade é implementada pelo FreeBSD a partir da versão 4.5, já o Linux introduziu a melhoria juntamente com NAPI, a partir da versão 2.6 do kernel, no entanto, esta é dependente do driver de dispositivo de rede que deve possuir suporte a polling para que seja explorada tal funcionalidade (DERI, 2004). Salim, Networks e Olsson (2001) definem que o hardware utilizado com intuito de solucionar o problema de livelock interrupt deve possuir suporte a duas tecnologias:
• Suporte a DMA (Direct memory access – Acesso direto a memória) ou memória RAM (Random Access Memory – Memória de acesso randômico) disponível para armazenar os pacotes em pseudo-dispositivos (software devices);
• Permitir desligamento das interrupções do hardware.
A introdução da técnica NAPI no kernel Linux foi essencial para solucionar, de forma genérica, a situação de baixo desempenho até então encontrada. Seu funcionamento, segundo Salim, Networks e Olsson (2001), tem por base tratar as seguintes questões:
• remover a reordenação de pacotes em SMP (Symmetric Multi-Processing – multriprocessamento simétrico);
• reduzir o overhead causado pela troca de contexto com os pedidos de interrupção tradicionais;
• remover ou reduzir as alocações injustas;
• promover o balanceamento entre latência e throughput; e
• não depender de hardware específico (apenas de tecnologias já normalmente encontradas).
Como solução veio a proposta de um sistema misto (Figura 18), na qual é utilizada a combinação dos mecanismos de interrupção e polling. De forma dinâmica, o primeiro mecanismo é utilizado em situações de pouca carga enquanto o polling entra em prática em grandes cargas de requisições da interface de rede. Essa flexibilidade é conseguida em função do MLFFR (Maximum Loss Free Forwarding Rate – índice máximo de repasse livre de perdas) (SALIM, NETWORKS &
OLSSON, 2001). A Figura 19 demonstra o funcionamento e o caminho dos dados implementado pela técnica NAPI.
Figura 19. Caminho dos dados da técnica NAPI Fonte: Adaptado de Salim, Networks e Olsson (2001)
A melhoria de desempenho conseguida pela nova implementação proposta (NAPI) pode ser observada na Figura 20, em que Deri (2004) em seus experimentos montou um gráfico comparativo entre sistemas de captura de pacotes com a libpcap confrontando polling com non-polling (sistemas sem polling).
Figura 20. Comparativo de performance de captura: polling vs. non-polling Fonte: Traduzido de Deri (2004).
Além da implementação NAPI através da técnica de device polling, como proposta de melhoria de desempenho para interfaces de redes para captura passiva de tráfego através da libpcap, Deri (2004) propôs melhorias para captura de pacotes através da observação quanto ao tráfego de informações que se fazia necessário entre a biblioteca libpcap (em espaço de usuário) e as estruturas em nível de kernel. “Muito tempo é gasto movendo os pacotes do adaptador de rede até o espaço de usuário através do kernel.” (DERI, 2004, tradução). Com isso um novo modelo de captura de pacotes foi proposto por Deri (2004) contemplando os seguintes requisitos:
• Projetar uma solução para melhorar o desempenho da captura de tráfego, a qual não estivesse ligada a um driver ou arquitetura de sistema operacional específica;
• considerando que adaptadores de rede são relativamente baratos, o objetivo é alocar um adaptador de rede especificamente para captura passiva o que permite aumentar o desempenho sem aumentar significativamente o custo;
• device polling realmente provê um aumento significativo de desempenho e deve ser explorado para promover toda melhoria esperada;
• por motivos de performance faz-se necessário permitir que os pacotes atravessem o kernel do SO para chegar ao espaço de usuário, contudo faz-se necessário diminuir o overhead causado por esta operação;
• a implementação padrão da libpcap, no caso de todos os pacotes serem movidos para espaço de usuário, sem a facilidade de filtragem prévia pelo kernel consome muito recurso de CPU.
A partir da necessidade de uma melhoria em relação à apresentada pela implementação NAPI, uma nova técnica, chamada PF_RING, foi proposta para a libpcap (DERI, 2004). Esta nova técnica considera os seguintes requisitos:
• Criação de um novo tipo de socket (PF_RING) que otimizasse a captura de pacotes com a cópia destes em um buffer cuja estrutura é uma fila circular;
• com o recebimento dos pacotes pela interface (normalmente com suporte DMA) estes seriam enviados para camadas superiores, ou seja, no caso com o PF_RING socket cada pacote recebido é copiado para a estrutura de fila circular;
• os pacotes armazenados nesta estrutura ficam disponíveis para as aplicações através de chamadas de sistemas do tipo mmap;
• por ser uma fila circular novos pacotes que chegam sobrescrevem os antigos, ou seja, não existe alocação e liberação de memória e simplesmente os pacotes são sobrescritos;
• o tamanho da estrutura de buffer é configurável pelo usuário.
Todas as características estão exemplificadas na Figura 21 que demonstra a arquitetura proposta para o PF_RING.
Figura 21. Arquitetura do socket PF_RING Fonte: Deri (2004)
Para fazer uso desta melhoria, Deri (2004) lembra que a biblioteca libpcap deve ser recompilada levando em conta a modificação (/ring/mmap-aware) que faz com que os pacotes capturados sejam armazenados na estrutura de buffer proposta e não mais em estruturas do núcleo
do sistema operacional. Além disso, o kernel Linux deve ser modificado através da inclusão do código modificado através do módulo PF_RING15.
Nesta Seção, foram apresentados alguns fatores que podem afetar o desempenho da captura passiva de pacotes com a libpcap e, com isso, estes fatores foram analisados na etapa experimental deste trabalho para identificar qual a relevância de cada um no desempenho da libpcap.