Problema de comunicação entre as interfaces do macvlan quando os soquetes estão ligados aos dispositivos

3

Eu tenho uma configuração Linux onde duas interfaces macvlan na ponte de modo são adicionadas na mesma interface física, na mesma sub-rede IP:

ip link add link eth2 dev mvl0 type macvlan mode bridge
ip link add link eth2 dev mvl1 type macvlan mode bridge
ip addr add 192.168.42.16/24 dev mvl0
ip addr add 192.168.42.17/24 dev mvl1
ip link set dev mvl0 up
ip link set dev mvl1 up

Eu quero me comunicar entre mvl0 e mvl1 usando soquetes vinculados às interfaces, mas isso não funciona. Por exemplo,

# ping -I mvl0 192.168.42.17

não recebe respostas. Eu posso ver que o kernel tenta fazer ARP em lo , mas isso não funciona, pois não recebe resposta.

  • Existe uma maneira de fazer isso funcionar, por exemplo, manipulando tabelas de roteamento ou vizinho?

  • Isso deve ser considerado um bug no kernel do Linux? Afinal, as interfaces macvlan no modo bridge devem poder ver uma à outra.

( Antecedentes: Esta é uma simulação de dois dispositivos incorporados em execução no mesmo contexto de processo. Nossa estrutura sempre liga sockets a interfaces, para garantir que a comunicação realmente passe pela interface desejada. A comunicação é normalmente via UDP.)

    
por starblue 17.10.2017 / 18:02

1 resposta

3

( Editar : A versão anterior só funcionava para pacotes de saída (UDP), esta versão funciona em ambas as direções (TCP e ping).)

Existem várias dicas para uma configuração como a sua: o Linux considera um pacote de entrada com um endereço de origem que corresponde a um endereço de interface de rede como um erro de roteamento (porque em circunstâncias normais indica um loop de roteamento). Além disso, por padrão, a tabela de roteamento local mantida pelo kernel tem a prioridade mais alta, e isso impedirá que seus pacotes saiam da interface à qual está vinculada.

Pode-se resolver o segundo problema com o roteamento de políticas: Primeiro, exclua as rotas sobrepostas (que só causarão problemas):

ip route list
# overlapping routes should look like:
ip route del 192.168.42.0/24 dev mvl0 proto kernel scope link src 192.168.42.16
ip route del 192.168.42.0/24 dev mvl1 proto kernel scope link src 192.168.42.17

Em seguida, atribua à tabela local uma prioridade mais baixa (maior valor numérico):

ip rule add pref 1000 lookup local
ip rule del pref 0

Precisamos aceitar pacotes de entrada enviando-os para a tabela local :

ip rule add pref 100 to 192.168.42.16 iif mvl0 lookup local
ip rule add pref 100 to 192.168.42.17 iif mvl1 lookup local

enquanto todos os outros pacotes (de saída) para o resp. destino usará uma tabela especial que os força a sair na outra interface:

ip rule add pref 200 to 192.168.42.17 lookup 100
ip rule add pref 200 to 192.168.42.16 lookup 101

ip route add default dev mvl0 table 100
ip route add default dev mvl1 table 101

Além disso, temos que cuidar do primeiro problema desabilitando a filtragem de caminho reverso (se já não estiver desabilitada) e permitindo que pacotes que tenham uma fonte local sejam aceitos:

echo "0" | tee /proc/sys/net/ipv4/conf/mvl{0,1}/rp_filter
echo "1" | tee /proc/sys/net/ipv4/conf/mvl{0,1}/accept_local

Agora, ping funciona mesmo se não estiver vinculado a uma das interfaces mvl . TCP e UDP também funcionam, testando com socat :

socat TCP4-LISTEN:9998,so-bindtodevice=mvl0 -
echo foo | socat - TCP4:192.168.42.16:9998,so-bindtodevice=mvl1

socat UDP4-RECV:9900,so-bindtodevice=mvl0 -
echo foo | socat - UDP4-SENDTO:192.168.42.16:9900,so-bindtodevice=mvl1
    
por 20.10.2017 / 14:07