kfree(mlxsw_sp_rt6);
 }
 
-static bool mlxsw_sp_fib6_rt_can_mp(const struct fib6_info *rt)
-{
-       /* RTF_CACHE routes are ignored */
-       return !(rt->fib6_flags & RTF_ADDRCONF) &&
-               rt->fib6_nh->fib_nh_gw_family;
-}
-
 static struct fib6_info *
 mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
 {
                                list)->rt;
 }
 
-static struct mlxsw_sp_fib6_entry *
-mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
-                                const struct fib6_info *nrt, bool replace)
-{
-       struct mlxsw_sp_fib6_entry *fib6_entry;
-
-       if (!mlxsw_sp_fib6_rt_can_mp(nrt) || replace)
-               return NULL;
-
-       list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
-               struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
-
-               /* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same
-                * virtual router.
-                */
-               if (rt->fib6_table->tb6_id > nrt->fib6_table->tb6_id)
-                       continue;
-               if (rt->fib6_table->tb6_id != nrt->fib6_table->tb6_id)
-                       break;
-               if (rt->fib6_metric < nrt->fib6_metric)
-                       continue;
-               if (rt->fib6_metric == nrt->fib6_metric &&
-                   mlxsw_sp_fib6_rt_can_mp(rt))
-                       return fib6_entry;
-               if (rt->fib6_metric > nrt->fib6_metric)
-                       break;
-       }
-
-       return NULL;
-}
-
 static struct mlxsw_sp_rt6 *
 mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry *fib6_entry,
                            const struct fib6_info *rt)
        kfree(fib6_entry);
 }
 
-static struct mlxsw_sp_fib6_entry *
-mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
-                             const struct fib6_info *nrt, bool replace)
-{
-       struct mlxsw_sp_fib6_entry *fib6_entry, *fallback = NULL;
-
-       list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
-               struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
-
-               if (rt->fib6_table->tb6_id > nrt->fib6_table->tb6_id)
-                       continue;
-               if (rt->fib6_table->tb6_id != nrt->fib6_table->tb6_id)
-                       break;
-               if (replace && rt->fib6_metric == nrt->fib6_metric) {
-                       if (mlxsw_sp_fib6_rt_can_mp(rt) ==
-                           mlxsw_sp_fib6_rt_can_mp(nrt))
-                               return fib6_entry;
-                       if (mlxsw_sp_fib6_rt_can_mp(nrt))
-                               fallback = fallback ?: fib6_entry;
-               }
-               if (rt->fib6_metric > nrt->fib6_metric)
-                       return fallback ?: fib6_entry;
-       }
-
-       return fallback;
-}
-
-static int
-mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry *new6_entry,
-                              bool *p_replace)
-{
-       struct mlxsw_sp_fib_node *fib_node = new6_entry->common.fib_node;
-       struct fib6_info *nrt = mlxsw_sp_fib6_entry_rt(new6_entry);
-       struct mlxsw_sp_fib6_entry *fib6_entry;
-
-       fib6_entry = mlxsw_sp_fib6_node_entry_find(fib_node, nrt, *p_replace);
-
-       if (*p_replace && !fib6_entry)
-               *p_replace = false;
-
-       if (fib6_entry) {
-               list_add_tail(&new6_entry->common.list,
-                             &fib6_entry->common.list);
-       } else {
-               struct mlxsw_sp_fib6_entry *last;
-
-               list_for_each_entry(last, &fib_node->entry_list, common.list) {
-                       struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(last);
-
-                       if (nrt->fib6_table->tb6_id > rt->fib6_table->tb6_id)
-                               break;
-                       fib6_entry = last;
-               }
-
-               if (fib6_entry)
-                       list_add(&new6_entry->common.list,
-                                &fib6_entry->common.list);
-               else
-                       list_add(&new6_entry->common.list,
-                                &fib_node->entry_list);
-       }
-
-       return 0;
-}
-
-static void
-mlxsw_sp_fib6_node_list_remove(struct mlxsw_sp_fib6_entry *fib6_entry)
-{
-       list_del(&fib6_entry->common.list);
-}
-
 static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp *mlxsw_sp,
-                                        struct mlxsw_sp_fib6_entry *fib6_entry,
-                                        bool *p_replace)
+                                        struct mlxsw_sp_fib6_entry *fib6_entry)
 {
+       struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
        int err;
 
-       err = mlxsw_sp_fib6_node_list_insert(fib6_entry, p_replace);
-       if (err)
-               return err;
+       list_add(&fib6_entry->common.list, &fib_node->entry_list);
 
        err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common);
        if (err)
        return 0;
 
 err_fib_node_entry_add:
-       mlxsw_sp_fib6_node_list_remove(fib6_entry);
+       list_del(&fib6_entry->common.list);
        return err;
 }
 
                                struct mlxsw_sp_fib6_entry *fib6_entry)
 {
        mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib6_entry->common);
-       mlxsw_sp_fib6_node_list_remove(fib6_entry);
+       list_del(&fib6_entry->common.list);
 }
 
 static struct mlxsw_sp_fib6_entry *
 }
 
 static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp *mlxsw_sp,
-                                       struct mlxsw_sp_fib6_entry *fib6_entry,
-                                       bool replace)
+                                       struct mlxsw_sp_fib6_entry *fib6_entry)
 {
        struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
        struct mlxsw_sp_fib6_entry *replaced;
 
-       if (!replace)
+       if (list_is_singular(&fib_node->entry_list))
                return;
 
+       /* We inserted the new entry before replaced one */
        replaced = list_next_entry(fib6_entry, common.list);
 
        mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, replaced);
        mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
 }
 
-static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
-                                   struct fib6_info **rt_arr,
-                                   unsigned int nrt6, bool replace)
+static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
+                                       struct fib6_info **rt_arr,
+                                       unsigned int nrt6)
 {
        struct mlxsw_sp_fib6_entry *fib6_entry;
        struct mlxsw_sp_fib_node *fib_node;
        if (IS_ERR(fib_node))
                return PTR_ERR(fib_node);
 
-       /* Before creating a new entry, try to append route to an existing
-        * multipath entry.
-        */
-       fib6_entry = mlxsw_sp_fib6_node_mp_entry_find(fib_node, rt, replace);
-       if (fib6_entry) {
-               err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry,
-                                                     rt_arr, nrt6);
-               if (err)
-                       goto err_fib6_entry_nexthop_add;
-               return 0;
-       }
-
        fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt_arr,
                                                nrt6);
        if (IS_ERR(fib6_entry)) {
                goto err_fib6_entry_create;
        }
 
-       err = mlxsw_sp_fib6_node_entry_link(mlxsw_sp, fib6_entry, &replace);
+       err = mlxsw_sp_fib6_node_entry_link(mlxsw_sp, fib6_entry);
        if (err)
                goto err_fib6_node_entry_link;
 
-       mlxsw_sp_fib6_entry_replace(mlxsw_sp, fib6_entry, replace);
+       mlxsw_sp_fib6_entry_replace(mlxsw_sp, fib6_entry);
 
        return 0;
 
 err_fib6_node_entry_link:
        mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
 err_fib6_entry_create:
+       mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
+       return err;
+}
+
+static int mlxsw_sp_router_fib6_append(struct mlxsw_sp *mlxsw_sp,
+                                      struct fib6_info **rt_arr,
+                                      unsigned int nrt6)
+{
+       struct mlxsw_sp_fib6_entry *fib6_entry;
+       struct mlxsw_sp_fib_node *fib_node;
+       struct fib6_info *rt = rt_arr[0];
+       int err;
+
+       if (mlxsw_sp->router->aborted)
+               return 0;
+
+       if (rt->fib6_src.plen)
+               return -EINVAL;
+
+       if (mlxsw_sp_fib6_rt_should_ignore(rt))
+               return 0;
+
+       fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id,
+                                        &rt->fib6_dst.addr,
+                                        sizeof(rt->fib6_dst.addr),
+                                        rt->fib6_dst.plen,
+                                        MLXSW_SP_L3_PROTO_IPV6);
+       if (IS_ERR(fib_node))
+               return PTR_ERR(fib_node);
+
+       if (WARN_ON_ONCE(list_empty(&fib_node->entry_list))) {
+               mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
+               return -EINVAL;
+       }
+
+       fib6_entry = list_first_entry(&fib_node->entry_list,
+                                     struct mlxsw_sp_fib6_entry, common.list);
+       err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt_arr,
+                                             nrt6);
+       if (err)
+               goto err_fib6_entry_nexthop_add;
+
+       return 0;
+
 err_fib6_entry_nexthop_add:
        mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
        return err;
        struct mlxsw_sp_fib_event_work *fib_work =
                container_of(work, struct mlxsw_sp_fib_event_work, work);
        struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
-       bool replace;
        int err;
 
        rtnl_lock();
        mlxsw_sp_span_respin(mlxsw_sp);
 
        switch (fib_work->event) {
-       case FIB_EVENT_ENTRY_REPLACE: /* fall through */
-       case FIB_EVENT_ENTRY_ADD:
-               replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
-               err = mlxsw_sp_router_fib6_add(mlxsw_sp,
-                                              fib_work->fib6_work.rt_arr,
-                                              fib_work->fib6_work.nrt6,
-                                              replace);
+       case FIB_EVENT_ENTRY_REPLACE_TMP:
+               err = mlxsw_sp_router_fib6_replace(mlxsw_sp,
+                                                  fib_work->fib6_work.rt_arr,
+                                                  fib_work->fib6_work.nrt6);
                if (err)
                        mlxsw_sp_router_fib_abort(mlxsw_sp);
                mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
                break;
-       case FIB_EVENT_ENTRY_DEL:
+       case FIB_EVENT_ENTRY_APPEND:
+               err = mlxsw_sp_router_fib6_append(mlxsw_sp,
+                                                 fib_work->fib6_work.rt_arr,
+                                                 fib_work->fib6_work.nrt6);
+               if (err)
+                       mlxsw_sp_router_fib_abort(mlxsw_sp);
+               mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
+               break;
+       case FIB_EVENT_ENTRY_DEL_TMP:
                mlxsw_sp_router_fib6_del(mlxsw_sp,
                                         fib_work->fib6_work.rt_arr,
                                         fib_work->fib6_work.nrt6);
        int err;
 
        switch (fib_work->event) {
-       case FIB_EVENT_ENTRY_REPLACE: /* fall through */
-       case FIB_EVENT_ENTRY_ADD: /* fall through */
-       case FIB_EVENT_ENTRY_DEL:
+       case FIB_EVENT_ENTRY_REPLACE_TMP: /* fall through */
+       case FIB_EVENT_ENTRY_APPEND: /* fall through */
+       case FIB_EVENT_ENTRY_DEL_TMP:
                fen6_info = container_of(info, struct fib6_entry_notifier_info,
                                         info);
                err = mlxsw_sp_router_fib6_work_init(&fib_work->fib6_work,
                                                     router->mlxsw_sp);
                return notifier_from_errno(err);
        case FIB_EVENT_ENTRY_ADD: /* fall through */
-       case FIB_EVENT_ENTRY_REPLACE:
+       case FIB_EVENT_ENTRY_REPLACE: /* fall through */
+       case FIB_EVENT_ENTRY_REPLACE_TMP: /* fall through */
+       case FIB_EVENT_ENTRY_APPEND:
                if (router->aborted) {
                        NL_SET_ERR_MSG_MOD(info->extack, "FIB offload was aborted. Not configuring route");
                        return notifier_from_errno(-EINVAL);