Linux:是否可以原子地替换路由表?

Linux:是否可以原子地替换路由表?

是否可以使用 ip route 或类似方法自动替换路由表?我想准备一个路由表,然后自动用新创建的路由表替换旧路由表。

ip 规则?

更新:我想准备一个路由表,并以原子操作替换当前活动的路由表。我需要从我自己的守护进程中执行此操作。

答案1

据我所知,Linux 中没有允许切换两个路由表或原子替换现有路由规则的功能。仍然可以实现如下所示的原子切换。所有中间规则的操作都是在任何步骤中真正原子化,没有任何警告。出于所有意图和目的,goto以下规则是可选的,即使没有它们,仍可实现准原子性。

算法:

  1. 先前状态:

    路由表 1000 已经添加,并且首选项为 20000 的规则正在对此表进行查找(这里没有选择器,因为 OP 没有提供此信息):

    $ ip -4 rule
    0:   from all lookup local
    20000:   from all lookup 1000
    32766:   from all lookup main
    32767:   from all lookup default
    
  2. 准备:

    路由表 1001 是预先用几个ip route add ... table 1001命令准备的。由于没有规则引用它,它仍然处于非活动状态。这就是将取代路由表 1000 的路由表。

  3. 添加新的路由规则(可能有其他选择器),并在稍后的首选项值中引用它,但首先使用规则

    ...指向查找主要的,因此在切换结束之前,甚至不存在旧路由表会影响某些数据包而新路由情况会同时影响其他数据包的情况。这应该无关紧要,goto如果不需要如此严格的原子性,则可以跳过下面的规则。

    ip rule add pref 20001 goto 32766
    ip rule add pref 20002 lookup 1001
    
  4. 自动切换到较新的路由表,其他 具有较早首选项的规则将跳过较旧路由表的规则和跳过较新路由表的规则。

    ip rule add pref 19999 goto 20002
    
  5. 清理

    ip rule del pref 20000
    ip rule del pref 20001
    ip rule del pref 19999
    
  6. 回到之前的状态:重复使用之前的路由表 ID 和路由规则首选项值

    • 在路由表 1000 上重复步骤 2 中对路由表 1001 执行的相同操作,首先刷新它

      ip route flush table 1000
      ip route add ... table 1000
      ...
      
    • 重置首选项并参考先前的状态并清理

      ip rule add pref 20000 lookup 1000
      ip rule del pref 20002
      ip route flush table 1001
      

    或者在下一次迭代中切换表 1000 和 1001 的角色可能会避免两次填充路线。

    状态现在回到步骤 1。

如果目标是取代主要的路由表,只需考虑它的表 ID 为 254(并且它是唯一的表(沿着当地的路由表)接收自动内核路由:最好始终使用noprefixroute地址并在这种情况下通过守护程序添加路由):上面的算法没有太多变化,除了可能替换goto 32766goto 32767类似更改。此外,路由表中添加的任何新路由(即使未引用)都需要验证自身或此表中已存在的路由或当前活动规则和引用表的路由。

相关内容