IEEE 802.1D MAC网桥过滤MAC组地址
LACP的协议是使用01-80-C2-00-00-0x范围内的MAC地址,这个范围在IEEE标准802.1D中定义为“MAC桥接过滤MAC组地址”。这是IEEE为使用链路本地组播与相邻设备通信的标准协议预留的范围。使用这些MAC地址的帧应该是显式链接本地的;引用IEEE标准组MAC地址教程:
IEEE 802.1D MAC Bridge Filtered MAC Group Addresses: 01-80-C2-00-00-00 to 01-80-C2-00-00-0F; MAC frames that have a destination MAC address within this range are not relayed by MAC bridges conforming to IEEE 802.1D.
IEEE 802.1D MAC网桥过滤MAC组地址:01-80- c2 -00-00至01-80-C2-00-00-0F;在此范围内具有目标MAC地址的MAC帧不会由符合IEEE 802.1的MAC桥接器中继。
IEEE维护了一个协议列表,如下列表:
MAC address | Protocol |
---|---|
01-80-C2-00-00-00 | Spanning Tree (STP/RSPT/MSTP) |
01-80-C2-00-00-01 | Ethernet Flow Control (pause frames) |
01-80-C2-00-00-02 | Link Aggregation Control Protocol (LACP) |
01-80-C2-00-00-03 | 802.1X Port-Based Network Access Control |
01-80-C2-00-00-08 | Provider Bridge protocols (STP) |
01-80-C2-00-00-0D | Provider Bridge protocols (MVRP) |
01-80-C2-00-00-0E | 802.1AB Link Layer Discovery Protocol (LLDP) |
实际应用中的问题
任何符合IEEE 802.1的桥接都必须过滤这些帧:要么处理它们,要么删除它们。在任何情况下,都不允许将它们连同其他接收器一起转发。这在2000年那时候是有道理的,那时网桥是硬件。但在虚拟化时代,情况就不同了。
比如,我使用基于kvm的主机来模拟多个虚拟网络设备。我使用Linux网桥来连接这些设备,当然,我希望网桥尽可能像一根电线一样直接连接我的虚拟设备。不幸的是,Linux桥接器编写得很好,符合IEEE 802.1,它使用01-80-C2-00-00-0x范围内的目标地址过滤所有以太网帧。这意味着我不能使用我的虚拟环境来测试上表中的任何协议。悲剧!
解决方法
可是我确实有需求在构建网络实验时测试LLDP、LACP、STP、802.1X,所以必须找到一个解决方案。显然,我不是第一个遇到这种情况的人,所以有一些解决方案。由于Linux内核2.6有一个设置,允许您通过在/sys/class/net/bridge-iface/bridge/group_fwd_mask中设置一个特定的位掩码,来控制从IEEE 802.1D中定义的桥接器应该转发的范围内的哪个本地帧。默认值0表示Linux桥接器不转发任何链接本地帧。例如,将这个值设置为16384将允许桥接转发LLDP帧(01-80-C2-00-00-0E):
echo 16384 > /sys/class/net/br0/bridge/group_fwd_mask
有个问题是:在默认内核发行版中,前三个MAC地址(-00、-01和-02)的位掩码值是受限制的,这意味着我们仍然不能使用这个技巧在我们的实验环境中启用STP和LACP协议。要删除这个限制,就需要自己对内核进行补丁并编译,就像EVE-NG中的人员所做的那样。为了简便,所以我只是从EVE-NG存储库中获取编译后的内核。现在,我们可以将group_fwd_mask设置为我们喜欢的任何值。
group_fwd_mask 掩码值解析
那么这个位掩码应该用什么值呢?位掩码是一个16位的数字,其中第1位代表MAC地址01-80- c2 -00-00,第16位代表01-80-C2-00-00-0F。默认值(所有位都是0)不转发任何链接本地帧。为了能够转发特定MAC地址的帧,我们需要将对应的位设置为1。例如,为了允许转发LLDP帧(01-80-C2-00-00-0E),我们需要将第15位设为1,其余的设为0:
MAC | 0F | 0E | 0D | 0C | 0B | 0A | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MAC | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
这意味着我们使用二进制数字0100 0000 0000作为位掩码,它翻译成十进制数字16384,就像我们在前面的示例中使用的一样。
如果我们想在mix中加入LACP (01-80-C2-00-00-02)和802.1X (01-80-C2-00-00-03),我们也会将第3位和第4位设为1:
MAC | 0F | 0E | 0D | 0C | 0B | 0A | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MAC | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
这导致二进制数0100 0000 0000 1100,在小数中是16396。使用此方法,您现在可以完全控制转发或筛选哪种类型的帧。
很简单对不对。对于我的实验环境,我只想允许尽可能多的协议,这样我就可以测试任何我想要的协议。所以我把所有的位都设为1:
对于打过补丁的内核,我可以使用所有的位:1111 1111 1111 1111 = 65535
对于未打补丁的内核,我不能使用前三位:1111 1111 1111 1000 = 65528
换句话说:要使开箱即用的Linux桥接器能够转发所有经过IEEE 802.1D MAC桥接器过滤的MAC组地址(受限制的三种类型除外),请执行以下命令:
echo 65528 > /sys/class/net/br0/bridge/group_fwd_mask
最后注意
在生产环境中,这可能不是最明智的做法,特别是使用修补过的内核泛洪STP BPDUs时。您最好只将其用于(虚拟)网络实验环境。祝你好运!