Quem mantém um firewall, proxy ou qualquer outro sistema que receba muitas conexões simultâneas deve ter se deparado com a mensagem “kernel: Neighbour table overflow“. Trata-se de um alerta sobre o estouro do limite da tabela ARP e as conesquencias disto pode ser a lentidão ou até mesmo perda de pacotes tornando as conexões de rede com esta máquina instável. O problema é resolvido facilmente. Veja como.
Os mais desesperados podem resolver o problema simplesmente fazendo assim:
# echo 16384 > /proc/sys/net/ipv4/neigh/default/gc_thresh1 # echo 32768 > /proc/sys/net/ipv4/neigh/default/gc_thresh2 # echo 65535 > /proc/sys/net/ipv4/neigh/default/gc_thresh3
Obviamente isso resolve o problema da grande maioria das pessoas que cehgarão a este texto por uma busca no Google, mas esta não é uma solução definitiva e nem é muito sensato fazer algo sem saber exatamente o que está sendo feito.
Entendendo o problema
A tabela ARP do Kernel do Linux tem um tamanho máximo que está definido dentro do arquivo /proc/sys/net/ipv4/neigh/default/gc_thresh3 e como era de se esperar se tem um tamanho máximo, ao ultrapassarmos este limite ela vai estourar.
E é isso que acontece quando vemos aquela mensagem nos logs dos nossos servidores. Quando a mensagem é exibida saiba que você já está com problemas e provavelmente você notará dificuldades para manter uma conexão com o servidor.
A solução vem com o aumento do limite desta tabela, mas não é muito legal você colocar a tabela no máximo. Existem outros parâmetros que você deve conhecer e que podem ajudá-lo a otimizar seu sistema.
As configurações da tabela ARP
Periodicamente o cache é verificado e as entradas mais antiga são removidas. O tempo em que isto ocorre é dado pelo intervalo definido em /proc/sys/net/ipv4/neigh/default/gc_interval que por padrão é de 30s.
Ou seja, a cada 30s o sistema analisa a tabela e chama o coletor de lixo (garbage colector) de acordo com as configurações dos outros três arquivos:
O arquivo /proc/sys/net/ipv4/neigh/default/gc_thresh1 define a quantidade mínima de endereços ARP que devem estar na tabela para que o coletor de lixo seja disparado.
Caso a tabela tenha menos endereços que o definido em gc_thresh1, o coletor não será evocado.
O arquivo /proc/sys/net/ipv4/neigh/default/gc_thresh2 define a quantidade máxima de endereços ARP que a tabela deverá suportar antes de chamar o coletor de lixo.
Caso a tabela tenha mais endereços que o definido em gc_thresh2, o coletor recolherá todos os endereços que estiverem lá por mais de 5s.
O arquivo /proc/sys/net/ipv4/neigh/default/gc_thresh3 define a quantidade máxima de endereços ARP que a tabela deverá suportar como um todo.
Caso a tabela tenha mais endereços que o definido em gc_thresh3, o coletor será executado imediatamente, removendo as entradas mais antigas e mantendo-a dentro do limite estipulado.
Configurando a tabela
Para saber quantos endereços temos na tabela basta usar o comando arp -n ou para obter apenas a quantidade use:
arp -an|wc -l
Isto envia a saída do comando arp (sem cabeçalhos) para o comando wc que conta o número de linhas retornadas.
Para sabermos o quanto a nossa tabela suporta bastaria olhar os três arquivos já citados. Uma dica para ve-los simultaneamente seria usando o comando grep assim:
grep . /proc/sys/net/ipv4/neigh/default/gc_thresh*
Claro que você poderia usar o cat para listar os arquivos individualmente, mas desta forma nós matamos três coelhos com uma cajadada só. A saída deverá ser algo assim:
/proc/sys/net/ipv4/neigh/default/gc_thresh1:128 /proc/sys/net/ipv4/neigh/default/gc_thresh2:512 /proc/sys/net/ipv4/neigh/default/gc_thresh3:1024
Existem três foras de alterarmos estes valores, sendo uma permanente e as outras duas enquanto o sistema não é reiniciado.
Uma já foi dada lá no início do artigo e só é válida até reiniciarmos o servidor. A segunda consiste em usar o comando sysctl que serve para configurar parâmetros do kernel em runtime.
# sysctl -w net.ipv4.neigh.default.gc_thresh3=2048
# sysctl -w net.ipv4.neigh.default.gc_thresh2=1024
# sysctl -w net.ipv4.neigh.default.gc_thresh1=512
Assim como da maneira anterior, este comando vai alterar os valores instantaneamente e permanecerá assim até que o sistema seja reiniciado.
Para que você mantenha os valores de forma permanente é preciso editar o arquivo de configuração do sysctl e definir estes valores lá.
Usando o seu editor de textos preferido edite o arquivo /etc/sysctl.conf e acrescene as seguintes linhas de acordo com a sua necessidade:
net.ipv4.neigh.default.gc_thresh3 = 2048
net.ipv4.neigh.default.gc_thresh2 = 1024
net.ipv4.neigh.default.gc_thresh1 = 512
Feito isso você pode recarregar as configurações para se certificar de que está tudo ok digitando o comando:
sysctl -p
Se nada der errado, então o trabalho está concluído.
Referências
Tobias Lachmann. Neighbour table overflow. Jan. 2010. Disponível em <http://blog.lachmann.org/2010/01/neighbour-table-overflow/>
Linuxman. Neighbour table overflow. Jan. 2010. Disponível em <http://linuxman.wikispaces.com/Neighbour+table+overflow>
Carlos Affonso Henriques. Eliminando o Neighbour table overflow. Mai. 2006. Disponível em <http://www.vivaolinux.com.br/dica/Eliminando-o-Neighbour-table-overflow>
Die.net. Manpage systcl. Disponível em <http://linux.die.net/man/8/sysctl>
Die.net. Manpage arp. Disponível em <http://linux.die.net/man/7/arp>
Ajudou mano obrigado.