简化,假设我有2个接口,eth0和eth1.我也有一个通过eth0的默认路由.
原始套接字的端点例如是10.10.10.10,eth1的地址是100.0.0.1,我在原始套接字的生命周期内执行以下操作:
ip -f inet route delete 10.10.10.10 ip -f inet route add 100.0.0.2 dev eth1 ip -f inet route add 10.10.10.10/32 via 100.0.0.2 dev eth1
现在我看到的是,在此操作之后,流量通过eth1正确地进行了几秒钟,然后它出错(通过eth0)一会儿(不到半秒)然后再次正确(据我所见)永久性).
所以我的主要问题是:
– 任何人都可以解释这里可能出现的问题吗?我尝试在前面提到的序列之后添加ip route flush cache但是没有做任何事情.我目前感到困惑的是为什么流量有时会被丢弃.我认为这可能是路由命令中的计时问题,或者是一段时间禁用路由的其他触发器,但我的选项已经用完了.
我确实尝试在我的原始套接字上使用SO_BINDTODEVICE选项,但是这没有多大帮助,主要区别在于当流量出错时根本不会发送,因为它会覆盖错误的接口.但是,我希望的是,这会将errno设置为类似E_CANNOTROUTE(这不存在),所以我可以捕获它并重试发送数据包.它目前没有这样做,但有没有办法可以捕捉到这样的失败?我(几乎)完全控制系统和运行套接字的应用程序.
我知道可以使用的一个解决方案是不使用L3原始套接字而是使用AF_PACKET套接字(并且我自己也使用ARP / ND),但我还是不想进入那个.
更新
通过更改此路由更改行为,我改进了系统中的行为.当我必须更新下一跳时,我现在查看已安装的路由并根据它采取行动:
>如果不存在,我只需安装新路线并跳过删除.
>如果确切的路线已经存在(相同的nh,相同的开发),我现在什么都不做.
>如果此路线存在另一个nh,我现在只对此nh进行更具体的删除,然后再添加.
虽然这可以稳定我的大部分问题,但我仍然有时会发现实际的删除添加发生时(尽管不那么经常)发生同样的事情(新机制中的最后一种情况).而且,这实际上仍然没有解释出现了什么问题(它只是绕过它),所以我现在就把这个问题保持开放,因为我真的很好奇这里出了什么问题.
仅供参考:我对centos有这个问题,据我所知,从centos4到centos6,32位.