Skip to content

Commit 0284696

Browse files
idoschdavem330
authored andcommitted
ipv6: Handle multipath route deletion notification
When an entire multipath route is deleted, only emit a notification if it is the first route in the node. Emit a replace notification in case the last sibling is followed by another route. Otherwise, emit a delete notification. Signed-off-by: Ido Schimmel <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Reviewed-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d2f0c9b commit 0284696

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

net/ipv6/route.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3749,6 +3749,7 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)
37493749

37503750
if (rt->fib6_nsiblings && cfg->fc_delete_all_nh) {
37513751
struct fib6_info *sibling, *next_sibling;
3752+
struct fib6_node *fn;
37523753

37533754
/* prefer to send a single notification with all hops */
37543755
skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any());
@@ -3764,7 +3765,32 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)
37643765
info->skip_notify = 1;
37653766
}
37663767

3768+
/* 'rt' points to the first sibling route. If it is not the
3769+
* leaf, then we do not need to send a notification. Otherwise,
3770+
* we need to check if the last sibling has a next route or not
3771+
* and emit a replace or delete notification, respectively.
3772+
*/
37673773
info->skip_notify_kernel = 1;
3774+
fn = rcu_dereference_protected(rt->fib6_node,
3775+
lockdep_is_held(&table->tb6_lock));
3776+
if (rcu_access_pointer(fn->leaf) == rt) {
3777+
struct fib6_info *last_sibling, *replace_rt;
3778+
3779+
last_sibling = list_last_entry(&rt->fib6_siblings,
3780+
struct fib6_info,
3781+
fib6_siblings);
3782+
replace_rt = rcu_dereference_protected(
3783+
last_sibling->fib6_next,
3784+
lockdep_is_held(&table->tb6_lock));
3785+
if (replace_rt)
3786+
call_fib6_entry_notifiers_replace(net,
3787+
replace_rt);
3788+
else
3789+
call_fib6_multipath_entry_notifiers(net,
3790+
FIB_EVENT_ENTRY_DEL_TMP,
3791+
rt, rt->fib6_nsiblings,
3792+
NULL);
3793+
}
37683794
call_fib6_multipath_entry_notifiers(net,
37693795
FIB_EVENT_ENTRY_DEL,
37703796
rt,

0 commit comments

Comments
 (0)