|
|
@@ -1384,9 +1384,49 @@ static void mlxsw_sp_netdevice_ipip_down_event(struct mlxsw_sp *mlxsw_sp,
|
|
|
mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
|
|
|
}
|
|
|
|
|
|
+static int mlxsw_sp_netdevice_ipip_vrf_event(struct mlxsw_sp *mlxsw_sp,
|
|
|
+ struct net_device *ol_dev)
|
|
|
+{
|
|
|
+ struct mlxsw_sp_fib_entry *decap_fib_entry;
|
|
|
+ struct mlxsw_sp_ipip_entry *ipip_entry;
|
|
|
+ struct mlxsw_sp_rif_ipip_lb *lb_rif;
|
|
|
+
|
|
|
+ ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
|
|
|
+ if (!ipip_entry)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* When a tunneling device is moved to a different VRF, we need to
|
|
|
+ * update the backing loopback. Since RIFs can't be edited, we need to
|
|
|
+ * destroy and recreate it. That might create a window of opportunity
|
|
|
+ * where RALUE and RATR registers end up referencing a RIF that's
|
|
|
+ * already gone. RATRs are handled by the RIF destroy, and to take care
|
|
|
+ * of RALUE, demote the decap route back.
|
|
|
+ */
|
|
|
+ if (ipip_entry->decap_fib_entry)
|
|
|
+ mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
|
|
|
+
|
|
|
+ lb_rif = mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp, ipip_entry->ipipt,
|
|
|
+ ol_dev);
|
|
|
+ if (IS_ERR(lb_rif))
|
|
|
+ return PTR_ERR(lb_rif);
|
|
|
+ mlxsw_sp_rif_destroy(&ipip_entry->ol_lb->common);
|
|
|
+ ipip_entry->ol_lb = lb_rif;
|
|
|
+
|
|
|
+ if (ol_dev->flags & IFF_UP) {
|
|
|
+ decap_fib_entry = mlxsw_sp_ipip_entry_find_decap(mlxsw_sp,
|
|
|
+ ipip_entry);
|
|
|
+ if (decap_fib_entry)
|
|
|
+ mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp, ipip_entry,
|
|
|
+ decap_fib_entry);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
int mlxsw_sp_netdevice_ipip_event(struct mlxsw_sp *mlxsw_sp,
|
|
|
struct net_device *ol_dev,
|
|
|
- unsigned long event)
|
|
|
+ unsigned long event,
|
|
|
+ struct netdev_notifier_changeupper_info *info)
|
|
|
{
|
|
|
switch (event) {
|
|
|
case NETDEV_REGISTER:
|
|
|
@@ -1399,6 +1439,11 @@ int mlxsw_sp_netdevice_ipip_event(struct mlxsw_sp *mlxsw_sp,
|
|
|
case NETDEV_DOWN:
|
|
|
mlxsw_sp_netdevice_ipip_down_event(mlxsw_sp, ol_dev);
|
|
|
return 0;
|
|
|
+ case NETDEV_CHANGEUPPER:
|
|
|
+ if (netif_is_l3_master(info->upper_dev))
|
|
|
+ return mlxsw_sp_netdevice_ipip_vrf_event(mlxsw_sp,
|
|
|
+ ol_dev);
|
|
|
+ return 0;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|