mlxsw: spectrum_router: Demote tunnels on VRF migration
authorPetr Machata <petrm@mellanox.com>
Tue, 28 Nov 2017 12:17:12 +0000 (13:17 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 28 Nov 2017 14:55:47 +0000 (09:55 -0500)
The mlxsw driver currently doesn't offload GRE tunnels if they have the
same local address and use the same underlay VRF. When such a situation
arises, the tunnels in conflict are demoted to slow path.

However, the current code only verifies this condition on tunnel
creation and tunnel change, not when a tunnel is moved to a different
VRF. When the tunnel has no bound device, underlay and overlay are the
same. Thus moving a tunnel moves the underlay as well, and that can
cause local address conflict.

So modify mlxsw_sp_netdevice_ipip_ol_vrf_event() to check if there are
any conflicting tunnels, and demote them if yes.

Fixes: af641713e97d ("mlxsw: spectrum_router: Onload conflicting tunnels")
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c

index c529e31fc78b75a022dedfedfff61f32db486b1d..a23e452f7261b9e67dc90920e25c4b9fa88e7192 100644 (file)
@@ -1449,9 +1449,27 @@ static int mlxsw_sp_netdevice_ipip_ol_vrf_event(struct mlxsw_sp *mlxsw_sp,
 {
        struct mlxsw_sp_ipip_entry *ipip_entry =
                mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
+       enum mlxsw_sp_l3proto ul_proto;
+       union mlxsw_sp_l3addr saddr;
+       u32 ul_tb_id;
 
        if (!ipip_entry)
                return 0;
+
+       /* For flat configuration cases, moving overlay to a different VRF might
+        * cause local address conflict, and the conflicting tunnels need to be
+        * demoted.
+        */
+       ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ol_dev);
+       ul_proto = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt]->ul_proto;
+       saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ol_dev);
+       if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp, ul_proto,
+                                                saddr, ul_tb_id,
+                                                ipip_entry)) {
+               mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
+               return 0;
+       }
+
        return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
                                                   true, false, false, extack);
 }