Eu tenho um aplicativo que está executando um soquete IP bruto, o destino desse soquete é governado por rotas instaladas por meio do comando 'ip route add'. Essas rotas podem mudar durante a vida útil de um soquete (por exemplo, devido às mudanças no próximo salto)
Simplificado, digamos que tenho 2 interfaces eth0
e eth1
. Eu também tenho uma rota padrão via eth0
.
O endpoint do soquete bruto é, por exemplo 10.10.10.10
, eth1 has address 100.0.0.1
, faço o seguinte durante a vida útil do soquete bruto:
ip -f inet route delete 10.10.10.10
ip -f inet route add 100.0.0.2 dev eth1
ip -f inet route add 10.10.10.10/32 via 100.0.0.2 dev eth1
Agora o que vejo é que depois desta operação o tráfego passa corretamente eth1
por alguns segundos, depois dá errado (via eth0) por um curto período (menos de meio segundo) e então está correto novamente (até onde posso ver permanentemente ).
Então a minha questão principal é: -Alguém pode dar uma explicação sobre o que pode dar errado aqui? Tentei adicionar ip route flush cache
após a sequência mencionada antes, mas não adiantou nada. No momento, estou intrigado com o motivo pelo qual o tráfego às vezes cai. Acho que é um problema de tempo nos comandos de roteamento ou algum outro gatilho que desativa a rota por uma fração de segundo, mas estou ficando sem opções.
Eu tentei usar a SO_BINDTODEVICE
opção no meu soquete bruto, mas isso não ajudou muito, a principal diferença é que quando o tráfego dá errado, ele não é enviadode forma alguma, porque passaria pela interface errada. No entanto, o que eu esperava era que isso configurasse errno para algo como E_CANNOTROUTE (isso não existe) para que eu pudesse capturar isso e tentar enviar o pacote novamente. Atualmente não faz isso, mas existe uma maneira de detectar tal falha? Tenho controle (quase) total sobre o sistema e o aplicativo que executa o soquete.
Uma solução que sei que funcionaria seria não usar soquetes brutos L3, mas AF_PACKET
soquetes (e também fazer ARP/ND), mas prefiro não entrar nisso ainda.
Atualizar
Melhorei o comportamento do meu sistema, alterando esse comportamento de mudança de rota. Quando tenho que atualizar o próximo salto, agora olho para a rota já instalada e tomo medidas com base nisso:
- Se não estiver lá, basta instalar a nova rota e pular a exclusão.
- Se a rota exata já estiver presente (mesmo nh, mesmo dev), agora não faço nada.
- Se outro nh estiver presente para esta rota, agora faço uma exclusão mais específica apenas para este nh seguida de uma adição.
Embora isso tenha estabilizado a maioria dos meus problemas, às vezes ainda vejo a mesma coisa acontecer (embora com muito menos frequência) quando ocorre uma exclusão + adição real (último caso no novo mecanismo). Além disso, isso ainda não explica o que está errado (apenas o contorna), então deixarei essa questão em aberto por enquanto, pois estou realmente curioso para saber o que está errado aqui.
Para sua informação: Tenho o problema no centos, pelo que posso ver indo de centos4 para centos6, 32 bits.
Responder1
Se bem entendi, os pacotes devem sempre sair da eth1, e seu problema é que ao atualizar para um novo nexthop na eth1 seus pacotes às vezes saem da eth0? Isso ocorre porque seu delete+add não é uma operação atômica.
Tente fazer a adição primeiro, seguida pela exclusão. A exclusão tem que ser específica (com o dispositivo e o próximo salto, acredito) para que não exclua também a nova rota que você acabou de adicionar.
Responder2
Existe uma rota padrão (ou outra rota cobrindo 10.10.10.10/32) via eth0? Se você estiver excluindo primeiro e depois adicionando, poderá ter uma condição de corrida em que a exclusão acontece, os pacotes saem pela rota padrão durante o tempo entre a exclusão e a adição, então a adição acontece e os pacotes começam a ir para onde você espera.
Definitivamente me parece alguma forma de condição de corrida, provavelmente devido à natureza não atômica das duas operações de roteamento que você mencionou (conforme declarado pela Lei 29).