Tive problemas de rede ultimamente (executando Debian, mas não específicos para nenhuma distro, veja abaixo usando manipulação direta de /sys), e descobri que a fonte dos meus problemas era que dois servidores com interfaces de rede vinculadas tinham o mesmo endereço de hardware em suas vinculações. Este endereço MAC NÃO é um dos endereços das interfaces de hardware, embora devesse ser (de acordo com a maioria das documentações, como esta ):
A interface de ligação tem um endereço de hardware de 00:00:00:00:00:00 até que o primeiro escravo seja adicionado. Se a interface VLAN for criada antes da primeira escravização, ela pegaria o endereço de hardware todo em zeros. Uma vez que o primeiro escravo é anexado à ligação, o próprio dispositivo de ligação pegará o endereço de hardware do escravo, que então fica disponível para o dispositivo VLAN.
Além disso, ao contrário do que é declarado nesta documentação, um vínculo "vazio" (sem nenhum escravo) não tem um endereço de hw 00:00:00:00:00:
# modprobe bonding
# echo +bond0 > /sys/class/net/bonding_masters
# ip link show bond0
3: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether d6:f5:8e:9f:c2:42 brd ff:ff:ff:ff:ff:ff
No entanto, esses endereços de hardware mudam para o endereço de hardware do escravo se e somente se o escravo for adicionado imediatamente ao vínculo e o endereço do vínculo não for verificado. Eu testo com um script muito simples (veja abaixo) para manipular o vínculo.
- Primeiro, ele cria um vínculo vazio sem escravos e exibe seu endereço de hardware (que aparentemente é pseudoaleatório, mas tende a permanecer o mesmo — talvez o udev tenha um papel aqui?).
- Em segundo lugar, ele cria o vínculo, define seu modo e adiciona um escravo: o vínculo pega o endereço de hardware do escravo conforme o esperado.
- Terceiro, ele cria o vínculo, lê seu endereço de hardware , define o modo e adiciona um escravo: o endereço de hardware do vínculo não corresponde ao endereço de hardware do escravo (mas executando o script repetidamente, de vez em quando ele corresponde! Vai entender).
- Quarto, ele cria o vínculo, espera um segundo e então o configura como na etapa 2. O comportamento é basicamente o mesmo da etapa 3: o vínculo tem o mesmo endereço de hardware pseudoaleatório da etapa 1, que sempre difere do endereço de hardware do escravo e é sempre o mesmo.
Não sei exatamente como o endereço de hardware pseudoaleatório do vínculo é configurado, mas ele é relativamente repetitivo em diversas configurações de hardware e software (hardware diferente, versões de kernel diferentes, versões de Debian diferentes).
Às vezes, no passo 3, o endereço MAC do bond muda para diferentes valores pseudoaleatórios, às vezes ele corresponde ao endereço do escravo. Na maioria das vezes, no entanto, ele permanece o mesmo do passo 1. No passo 4, o endereço MAC do bond é sempre o mesmo do passo um.
Aparentemente a configuração do endereço MAC do vínculo é muito sensível ao tempo?
Aqui está o roteiro:
echo "unload / load bonding"
rmmod bonding
sleep 1
modprobe bonding
sleep 1
echo "create bond0"
echo +bond0 > /sys/class/net/bonding_masters
echo "bond0 hw address, no slaves:"
cat /sys/class/net/bond0/address
sleep 3
echo "################"
echo "unload / load bonding"
rmmod bonding
sleep 1
modprobe bonding
sleep 1
echo "create bond0 and configure it without delay"
echo +bond0 > /sys/class/net/bonding_masters
# cat /sys/class/net/bond0/address
echo 6 > /sys/class/net/bond0/bonding/mode
echo +enp1s0 > /sys/class/net/bond0/bonding/slaves
echo "Bond0 hw address:"
cat /sys/class/net/bond0/address
echo "enp1s0 hw address:"
ethtool -P enp1s0
echo "################"
sleep 3
echo "unload / load bonding"
rmmod bonding
sleep 1
modprobe bonding
sleep 1
echo "create bond0 and configure it, read its hw address first"
echo +bond0 > /sys/class/net/bonding_masters
cat /sys/class/net/bond0/address
echo 6 > /sys/class/net/bond0/bonding/mode
echo +enp1s0 > /sys/class/net/bond0/bonding/slaves
echo "Bond0 hw address:"
cat /sys/class/net/bond0/address
echo "enp1s0 hw address:"
ethtool -P enp1s0
echo "################"
sleep 3
echo "unload / load bonding"
rmmod bonding
sleep 1
modprobe bonding
sleep 1
echo "create bond0 and configure it after 1 second delay"
echo +bond0 > /sys/class/net/bonding_masters
# cat /sys/class/net/bond0/address
echo 6 > /sys/class/net/bond0/bonding/mode
sleep 1
echo +enp1s0 > /sys/class/net/bond0/bonding/slaves
echo "Bond0 hw address:"
cat /sys/class/net/bond0/address
echo "enp1s0 hw address:"
ethtool -P enp1s0
E aqui está a saída:
unload / load bonding
create bond0
bond0 hw address, no slaves:
ea:dc:34:e6:7c:8d
################
unload / load bonding
create bond0 and configure it without delay
Bond0 hw address:
52:54:00:c8:76:09
enp1s0 hw address:
Permanent address: 52:54:00:c8:76:09
################
unload / load bonding
create bond0 and configure it, read its hw address first
d6:f5:8e:9f:c2:42
Bond0 hw address:
d6:f5:8e:9f:c2:42
enp1s0 hw address:
Permanent address: 52:54:00:c8:76:09
################
unload / load bonding
create bond0 and configure it after 1 second delay
Bond0 hw address:
d6:f5:8e:9f:c2:42
enp1s0 hw address:
Permanent address: 52:54:00:c8:76:09
De tempos em tempos, o endereço hw do bond muda para algum outro valor. No entanto, na maioria das vezes ele volta para o mesmo (aqui 'd6:f5:8e:9f:c2:42') e parece circular por um número limitado de endereços MAC entre reinicializações.
No entanto, o problema muito sério é que máquinas diferentes acabam com o mesmo endereço de hardware pseudoaleatório; quando estão conectadas ao mesmo switch de rede, o caos se instala. Na verdade, verificando em várias máquinas diferentes conectadas a redes diferentes, pelo menos 4 compartilham o mesmo endereço MAC de ligação (embora, desde que não estejam conectadas juntas ao mesmo switch, é basicamente inofensivo).
Observe que naquele exemplo em particular eu configurei o bond no modo 6, mas tive o problema na máquina rodando no modo 4 (802.3ad) e outros modos. Isso não parece relacionado ao modo de bonding de forma alguma -- mudar o mais para 1 ou 2 ou 4 não muda o endereço MAC.
É claro que eu poderia forçar o endereço MAC do vínculo para algum valor significativo usando um script if-up.d ou algo semelhante, mas prefiro ter algo que funcione imediatamente :)
Há algum tempo há problemas com os endereços MAC usados no bonding do Linux (modo 4); no passado, o MAC da primeira interface no bonding era usado, o que era bom quando um novo agregado ativo era determinado somente após falha/desconexão completa do agregado ativo.
Tudo mudou quando o código foi alterado para selecionar um novo agregado ativo em cada alteração nas interfaces vinculadas, o que permitiu selecionar o agregado com mais largura de banda/links/etc. em cada alteração.
E é aí que os problemas começam; imagine o seguinte:
Tudo estava bem no agregado ativo 1, mas após alternar para o agregado 2, o eth0 ainda está conectado com seu próprio endereço mac e o agregado 2 também está usando esse mac no outro switch! Isso porque (modo 4/802.3ad/lacp) os mantém conectados/monitorados para mudanças de estado, resultando em cerca de 20% ou mais de perda de pacotes...
Já vi isso acontecer em muitos locais e até mesmo com aparelhos como os NetApp Filers, e o que acabo fazendo é definir o mac para o vínculo para um endereço mac privado com base no mac do eth0, apenas substituindo o primeiro octeto por
02
:Dessa forma, o Mac no vínculo é único e rastreável/vinculável ao hardware real usado.
Notei que algumas distribuições recentemente começaram a usar/configurar Macs privados para interfaces vinculadas automaticamente, mas gosto de manter isso sob meu próprio controle...