添加/删除路线后的时序问题(路线未使用)

添加/删除路线后的时序问题(路线未使用)

我有一个运行原始 IP 套接字的应用程序,此套接字的目标由通过“ip route add”命令安装的路由控制。这些路由可以在套接字的生命周期内发生变化(例如,因为下一跳发生变化)

简单来说,假设我有 2 个接口,eth0eth1。我还有一个通过的默认路由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,相同的 dev),我现在不执行任何操作。
  • 如果此路线存在另一个 nh,我现在将针对此 nh 进行更具体的删除,然后进行添加。

虽然这稳定了我的大部分问题,但当实际发生删除+添加时(新机制中的最后一种情况),我有时仍会看到同样的事情发生(尽管频率要低得多)。此外,这实际上仍然没有解释出了什么问题(它只是绕过了它),所以我暂时不回答这个问题,因为我真的很好奇这里出了什么问题。

仅供参考:我在 centos 上遇到了这个问题,据我所知,从 centos4 升级到 centos6,32 位。

答案1

如果我理解正确的话,数据包应该始终从 eth1 发出,而您的问题是,在 eth1 上更新到新的下一跳时,您的数据包有时会从 eth0 发出?那是因为您的删除+添加不是原子操作。

尝试先添加,然后再删除。删除必须是具体的(我相信是针对设备和下一跳),这样它就不会删除您刚添加的新路由。

答案2

是否有通过 eth0 的默认路由(或覆盖 10.10.10.10/32 的其他路由)?如果您先删除然后添加,则可能会出现竞争条件,即删除发生时,数据包在删除和添加之间的时间内从默认路由发出,然后添加发生并且数据包开始到达您期望的位置。

对我来说,这听起来确实像是某种形式的竞争条件,很可能是由于您提到的两个路由操作的非原子性质(如 Law29 所述)。

相关内容