【内核】Linux内核参数group_fwd_mask-设置bridge过滤MAC地址范围

笔者在利用gns3模拟器搭建网络实验时,发现交换机设备和服务器之间无法成功协商LACP协议,CISCO NEXUS 9K互相之间却可以成功协商LACP, 在交换机和服务器上抓包发现,Nexus 9K发出的LACP报文中的目的MAC地址为00:01:02:03:04:05(而标准LACP协议中规定的是01:80:c2:00:00:02),服务器发出的LACP报文的目的MAC是01:80:c2:00:00:02。然而,进一步思考,为什么在gns3模拟器中, Nexus 9K的LACP的目标MAC跟标准协议不同呢?经过查阅,这是因为在gns3上的所有虚拟设备都是运行在同一个物理服务器上,互相之间通过网桥相连,默认情况下,linux的网桥会将01:80:c2:00:00:0x的目标MAC地址全部过滤,Nexus 9K为了避免该问题调整了LACP的目标MAC, 而服务器却没有调整。调整group_fwd_mask这个内核参数,可以控制linux网桥对MAC地址的过滤范围,这也是本文想要探讨的问题。

IEEE 802.1D协议中规定的网桥过滤MAC地址

下面一段话引用自IEEE Standard Group MAC Addresses tutorial,IEEE 802.1D协议规定,01-80-C2-00-00-00  -- 01-80-C2-00-00-0F是IEEE为标准协议留出的范围,使用这些地址的包将被网桥过滤,而不会被转发。

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协议中规定的预留的MAC地址表如下:

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)

 

 

出现的问题

所有使用上述MAC地址的协议,都会被网桥过滤掉(因为网桥符合IEEE 802.1D协议的规定),如果使用的是物理网桥,这样的情况将无法改变,但是对于linux中的虚拟网桥呢,是不是也是一样呢?默认情况下,linux的虚拟网桥完全符合IEEE 802.1D的规定,跟物理网桥一样,完全过滤了目的MAC地址为01-80-C2-00-00-0x的协议,因此造成了本文开头所述的情况。

解决方法

那怎样才能在gns3上模拟这么多被过滤的协议呢?显然一定还有其他人遇到过相同的问题,只要google一下便不难找到解决方法了。从Linux Kernel 2.6开始,就可以通过调整内核参数/sys/class/net/bridge-iface/bridge/group_fwd_mask来控制虚拟网桥对802.1D中规定的地址范围中,哪些MAC地址不再过滤。/sys/class/net/bridge-iface/bridge/group_fwd_mask的默认值为0,意味着将对01-80-C2-00-00-0x的所有地址进行过滤。将/sys/class/net/bridge-iface/bridge/group_fwd_mask的值设为16384, 则可以让虚拟网桥转发LLDP报文(目的MAC:  01-80-C2-00-00-0E)

echo 16384 > /sys/class/net/br0/bridge/group_fwd_mask

 需要注意的是,在默认的发行版本中,对于该MAC地址范围中的前三个(-00,-01,-02)是不能通过以上方式控制的, 意味着在gns3的模拟环境中,我们仍然不能成功的测试STP,流控和LACP。要克服这个限制,必须要自己编译linux kernel才行,点击查看方法,也可以下载EVE编译好的版本,点击进入链接。这样就可以随意调整group_fwd_mask的值,支持不过滤01-80-C2-00-00-0x的所有地址了。

bitmasks和group_fwd_mask

前文中把group_fwd_mask设为16384,对应的MAC是01-80-C2-00-00-0E,对应的协议是LLDP, 那么group_fwd_mask是如何计算的呢?

例1: 如果要允许01-80-C2-00-00-0E,对应的表格如下,MAC地址的最后两位是0E, 则将下表中的0E的bit置为1。

MAC 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
BIT 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0

 

bitmasks是二进制数0100 0000 0000 0000, 转换成10进制则为16384。

例2: 如果要允许01-80-C2-00-00-0E,01-80-C2-00-00-03,01-80-C2-00-00-02, 则对应的表如下, 将表中的0E,03,02的bit置为1。

MAC 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
BIT 0 1 0 0 0 0 0 0 0 0 0 0 0 0

bitmasks是二进制数0100 0000 0000 1100, 转换成10进制则为16396。这样就可以允许LLDP,LACP,802.1x协议了。

按照这样的方法,要解除linux网桥对规定地址范围内所有地址的过滤,就把所有的bit都置为1 即可:

  1. 打过patch的kernel: 
    echo 65535 > /sys/class/net/br0/bridge/group_fwd_mask
  2. 官方kernel(最后3位不能为1):
    echo 65528 > /sys/class/net/br0/bridge/group_fwd_mask

注意 

在生产环境中要慎用这个参数,否则可能造成bridge转发很多不必要的包造成网络风暴引起故障或性能下降。但在使用linux搭建虚拟网络实验环境时还是非常有用的,可以实现各种协议的模拟。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章