return err;
 }
 
+struct mlxsw_sp_router_replay_inetaddr_up {
+       struct mlxsw_sp *mlxsw_sp;
+       struct netlink_ext_ack *extack;
+       unsigned int done;
+};
+
+static int mlxsw_sp_router_replay_inetaddr_up(struct net_device *dev,
+                                             struct netdev_nested_priv *priv)
+{
+       struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data;
+       struct mlxsw_sp_crif *crif;
+       int err;
+
+       if (mlxsw_sp_dev_addr_list_empty(dev))
+               return 0;
+
+       crif = mlxsw_sp_crif_lookup(ctx->mlxsw_sp->router, dev);
+       if (!crif || crif->rif)
+               return 0;
+
+       if (!mlxsw_sp_rif_should_config(crif->rif, dev, NETDEV_UP))
+               return 0;
+
+       err = __mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_UP,
+                                       false, ctx->extack);
+       if (err)
+               return err;
+
+       ctx->done++;
+       return 0;
+}
+
+static int mlxsw_sp_router_unreplay_inetaddr_up(struct net_device *dev,
+                                               struct netdev_nested_priv *priv)
+{
+       struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data;
+       struct mlxsw_sp_crif *crif;
+
+       if (!ctx->done)
+               return 0;
+
+       if (mlxsw_sp_dev_addr_list_empty(dev))
+               return 0;
+
+       crif = mlxsw_sp_crif_lookup(ctx->mlxsw_sp->router, dev);
+       if (!crif || !crif->rif)
+               return 0;
+
+       /* We are rolling back NETDEV_UP, so ask for that. */
+       if (!mlxsw_sp_rif_should_config(crif->rif, dev, NETDEV_UP))
+               return 0;
+
+       __mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_DOWN, false, NULL);
+
+       ctx->done--;
+       return 0;
+}
+
+int mlxsw_sp_netdevice_enslavement_replay(struct mlxsw_sp *mlxsw_sp,
+                                         struct net_device *upper_dev,
+                                         struct netlink_ext_ack *extack)
+{
+       struct mlxsw_sp_router_replay_inetaddr_up ctx = {
+               .mlxsw_sp = mlxsw_sp,
+               .extack = extack,
+       };
+       struct netdev_nested_priv priv = {
+               .data = &ctx,
+       };
+       int err;
+
+       err = mlxsw_sp_router_replay_inetaddr_up(upper_dev, &priv);
+       if (err)
+               return err;
+
+       err = netdev_walk_all_upper_dev_rcu(upper_dev,
+                                           mlxsw_sp_router_replay_inetaddr_up,
+                                           &priv);
+       if (err)
+               goto err_replay_up;
+
+       return 0;
+
+err_replay_up:
+       netdev_walk_all_upper_dev_rcu(upper_dev,
+                                     mlxsw_sp_router_unreplay_inetaddr_up,
+                                     &priv);
+       mlxsw_sp_router_unreplay_inetaddr_up(upper_dev, &priv);
+       return err;
+}
+
 static int
 mlxsw_sp_port_vid_router_join_existing(struct mlxsw_sp_port *mlxsw_sp_port,
                                       u16 vid, struct net_device *dev,
        return err;
 }
 
+static void
+__mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port,
+                                struct net_device *lag_dev)
+{
+       u16 default_vid = MLXSW_SP_DEFAULT_VID;
+       struct net_device *upper_dev;
+       struct list_head *iter;
+       u16 vid;
+
+       netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) {
+               if (!is_vlan_dev(upper_dev))
+                       continue;
+
+               vid = vlan_dev_vlan_id(upper_dev);
+               mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, vid, upper_dev);
+       }
+
+       mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, default_vid, lag_dev);
+}
+
 int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
                                  struct net_device *lag_dev,
                                  struct netlink_ext_ack *extack)
        return err;
 }
 
+void mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port,
+                                   struct net_device *lag_dev)
+{
+       mutex_lock(&mlxsw_sp_port->mlxsw_sp->router->lock);
+       __mlxsw_sp_router_port_leave_lag(mlxsw_sp_port, lag_dev);
+       mutex_unlock(&mlxsw_sp_port->mlxsw_sp->router->lock);
+}
+
 static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
                                           unsigned long event, void *ptr)
 {