我最近遇到了网络问题(运行 Debian,但不特定于任何发行版,请参见下文使用直接 /sys 操作),我发现问题的根源是两台具有绑定网络接口的服务器在其绑定上具有相同的硬件地址。此 MAC 地址不是硬件接口的地址之一,尽管它应该是(根据大多数文档,例如本文档):
在添加第一个从属设备之前,绑定接口的硬件地址为 00:00:00:00:00:00。如果在第一次从属设备之前创建了 VLAN 接口,它将获取全零硬件地址。一旦第一个从属设备连接到绑定,绑定设备本身将获取从属设备的硬件地址,然后该地址可供 VLAN 设备使用。
此外,与本文档中所述相反,“空”债券(没有任何从属)没有 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
但是,只有当从设备立即添加到绑定中并且不检查绑定地址时,该硬件地址才会更改为从设备的硬件地址。我使用一个非常简单的脚本(见下文)测试如何操作绑定。
- 首先,它创建一个没有从属设备的空键,并显示其硬件地址(显然是伪随机的,但趋于保持不变 - 也许 udev 在这里发挥了作用?)。
- 其次,它创建结合、设置其模式并添加从属设备:结合设备按预期采用从属设备的硬件地址。
- 第三,它创建绑定,读取它的硬件地址,然后设置模式并添加从属:绑定的硬件地址与其从属的硬件地址不匹配(但一次又一次地运行脚本,有时会匹配!去想想)。
- 第四,它创建绑定,等待一秒钟,然后像步骤 2 那样进行配置。其行为与步骤 3 大致相同:绑定具有与步骤 1 相同的伪随机硬件地址,该地址始终与从属设备的硬件地址不同且始终相同。
我不知道 bond 伪随机硬件地址究竟是如何设置的,但它恰好在多个硬件和软件配置(不同的硬件、不同的内核版本、不同的 Debian 版本)中相对重复。
有时,在步骤 3 中,绑定的 MAC 地址会更改为不同的伪随机值,有时它会与从属的地址匹配。但大多数情况下,它会与步骤 1 中保持相同。在步骤 4 中,绑定的 MAC 地址始终与步骤 1 相同。
显然,绑定的 MAC 地址设置对时间非常敏感?
脚本如下:
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
它的输出如下:
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
有时,绑定的硬件地址会更改为其他值。但是,大多数情况下它会恢复为同一个值(此处为“d6:f5:8e:9f:c2:42”),并且似乎在重新启动时循环使用有限数量的 MAC 地址。
然而,非常严重的问题是,不同的机器最终会拥有相同的伪随机硬件地址;当它们连接到同一个网络交换机时,就会出现混乱。实际上,检查连接到不同网络的几台不同机器,至少有 4 台共享相同的绑定 MAC 地址(但只要它们没有连接到同一个交换机,这基本上是无害的)。
请注意,在该特定示例中,我以模式 6 设置了绑定,但我在以模式 4 (802.3ad) 和其他模式运行的机器上遇到了问题。这似乎与绑定模式完全无关 - 将更多更改为 1 或 2 或 4 不会更改 MAC 地址。
当然,我可以使用 if-up.d 脚本或类似的东西将绑定的 MAC 地址强制为某个有意义的值,但我宁愿使用开箱即用的东西 :)
很长一段时间以来,Linux 绑定(模式 4)中使用的 mac 地址一直存在问题;过去使用绑定中第一个接口的 mac,当仅在活动聚合完全故障/断开连接后才确定新的活动聚合时,这是没问题的。
当代码更改为在绑定接口上的每次更改上选择一个新的活动聚合时,这一切都发生了变化,这允许在每次更改时选择具有最多带宽/链接/等的聚合。
这就是问题开始的地方;想象一下:
活动聚合 1 上一切正常,但切换到聚合 2 后,eth0 仍与其自己的 mac 地址相连,而聚合 2 也在另一台交换机上使用此 mac!这是因为(模式 4/802.3ad/lacp)使它们保持连接/监视状态变化,导致大约 20% 或更多的数据包丢失...
我在许多地方都看到过这种情况,甚至在 NetApp Filers 等设备上也发生过这种情况,我最终倾向于将绑定的 mac 设置为基于 eth0 的 mac 的私有 mac 地址,只需将第一个八位字节替换为
02
:这样,绑定上的 mac 就是唯一的,并且可以跟踪/链接到实际使用的硬件。
我确实注意到一些发行版最近开始自动使用/设置绑定接口的私有 mac,但我喜欢将其置于自己的控制之下……