man一下ebtables即可知道,或者随便想一下也会知道,ebtables在OUTPUT链上可以做DNAT,修改目的MAC地址,和iptables一样,到达OUTPUT链的时候已经经过路由表了,只不过对于桥设备,该路由表是一个“MAC地址-出口设备”的映射表。我们知道,IP层的OUTPUT链上作了DNAT后需要重新路由,这是IP-DNAT这个target自己完成的,在IP-OUTPUT的钩子函数中调用了ip_route_me_harder重新路由,然而在链路层的BR-OUTPUT中我们没有发现重新路由的代码,这样会有问题吗?如果做一个实验,发现这样是有问题的,一个桥两个口,分别是1和2,如果本地发出的包准备从2发出,此时发生了DNAT,DNAT的结果目的MAC位于1的那一侧,由于没有重新路由(查找地址-端口映射表),数据帧依然从2发出,启动了STP的网络,数据帧将永远到达不了目的地,这就出了问题了...
且慢,虽然这是个问题,然而以太网链路层的路由和IP路由却是两码事,其机制一点都不一样,可以说链路层的路由是自动学习得到的,其方式就是众所周知的交换机学习,而IP路由却是需要显式配置的,虽然有所谓的动态路由协议,但是还是需要应用层程序的帮助,对于自动学习的表项,它早晚是要收敛的,也就是说即使没有重新路由,由于链路层设备遵循要么往特定出口发,要么泛洪,所以DNAT后的目的地址早晚会被桥设备学习到的,链路层的映射表永远都处于一种躁动不安的状态,不像IP路由,一旦有个永久的静态路由,OUTPUT中执行了DNAT不重新路由就杯具了...
既然链路层可以自动学习映射表,无需人工帮助,那么BR-OUTPUT之后不打扰这种机制也是必要的,为何要重新路由呢?此时说不定正在泛洪,你再重路由就要重新泛洪,本来在n个口泛洪,每个口执行了DNAT后重路由都可能要再次泛洪...只要DNAT后的目的设备发一个包到达桥设备,就算学习成功了。只有在DNAT之前和之后永久的位于不同侧的时候才会出现不通的问题,如果你的网络足够大,启用了STP,那么不同时刻两个地址是否位于同侧是不一定的。
因此,我觉的在泛洪时不重新路由,而不泛洪时重新路由,这样比较好。
且慢,虽然这是个问题,然而以太网链路层的路由和IP路由却是两码事,其机制一点都不一样,可以说链路层的路由是自动学习得到的,其方式就是众所周知的交换机学习,而IP路由却是需要显式配置的,虽然有所谓的动态路由协议,但是还是需要应用层程序的帮助,对于自动学习的表项,它早晚是要收敛的,也就是说即使没有重新路由,由于链路层设备遵循要么往特定出口发,要么泛洪,所以DNAT后的目的地址早晚会被桥设备学习到的,链路层的映射表永远都处于一种躁动不安的状态,不像IP路由,一旦有个永久的静态路由,OUTPUT中执行了DNAT不重新路由就杯具了...
既然链路层可以自动学习映射表,无需人工帮助,那么BR-OUTPUT之后不打扰这种机制也是必要的,为何要重新路由呢?此时说不定正在泛洪,你再重路由就要重新泛洪,本来在n个口泛洪,每个口执行了DNAT后重路由都可能要再次泛洪...只要DNAT后的目的设备发一个包到达桥设备,就算学习成功了。只有在DNAT之前和之后永久的位于不同侧的时候才会出现不通的问题,如果你的网络足够大,启用了STP,那么不同时刻两个地址是否位于同侧是不一定的。
因此,我觉的在泛洪时不重新路由,而不泛洪时重新路由,这样比较好。