diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index a6c0479c1d55f8f52b71449895ff56b5903f2ce2..bbb5ffb3397d8b98227c81023cac218603822619 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1081,8 +1081,24 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, err = call_fib6_entry_notifiers(info->nl_net, FIB_EVENT_ENTRY_ADD, rt, extack); - if (err) + if (err) { + struct fib6_info *sibling, *next_sibling; + + /* If the route has siblings, then it first + * needs to be unlinked from them. + */ + if (!rt->fib6_nsiblings) + return err; + + list_for_each_entry_safe(sibling, next_sibling, + &rt->fib6_siblings, + fib6_siblings) + sibling->fib6_nsiblings--; + rt->fib6_nsiblings = 0; + list_del_init(&rt->fib6_siblings); + rt6_multipath_rebalance(next_sibling); return err; + } rcu_assign_pointer(rt->fib6_next, iter); atomic_inc(&rt->fib6_ref);