[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20191223132820.888247-8-idosch@idosch.org>
Date: Mon, 23 Dec 2019 15:28:18 +0200
From: Ido Schimmel <idosch@...sch.org>
To: netdev@...r.kernel.org
Cc: davem@...emloft.net, dsahern@...il.com, roopa@...ulusnetworks.com,
jakub.kicinski@...ronome.com, jiri@...lanox.com,
Ido Schimmel <idosch@...lanox.com>
Subject: [PATCH net-next 7/9] ipv6: Handle multipath route deletion notification
From: Ido Schimmel <idosch@...lanox.com>
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 <idosch@...lanox.com>
Reviewed-by: Jiri Pirko <jiri@...lanox.com>
---
net/ipv6/route.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c0809f52f9ef..646716a47cc9 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -3749,6 +3749,7 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)
if (rt->fib6_nsiblings && cfg->fc_delete_all_nh) {
struct fib6_info *sibling, *next_sibling;
+ struct fib6_node *fn;
/* prefer to send a single notification with all hops */
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)
info->skip_notify = 1;
}
+ /* 'rt' points to the first sibling route. If it is not the
+ * leaf, then we do not need to send a notification. Otherwise,
+ * we need to check if the last sibling has a next route or not
+ * and emit a replace or delete notification, respectively.
+ */
info->skip_notify_kernel = 1;
+ fn = rcu_dereference_protected(rt->fib6_node,
+ lockdep_is_held(&table->tb6_lock));
+ if (rcu_access_pointer(fn->leaf) == rt) {
+ struct fib6_info *last_sibling, *replace_rt;
+
+ last_sibling = list_last_entry(&rt->fib6_siblings,
+ struct fib6_info,
+ fib6_siblings);
+ replace_rt = rcu_dereference_protected(
+ last_sibling->fib6_next,
+ lockdep_is_held(&table->tb6_lock));
+ if (replace_rt)
+ call_fib6_entry_notifiers_replace(net,
+ replace_rt);
+ else
+ call_fib6_multipath_entry_notifiers(net,
+ FIB_EVENT_ENTRY_DEL_TMP,
+ rt, rt->fib6_nsiblings,
+ NULL);
+ }
call_fib6_multipath_entry_notifiers(net,
FIB_EVENT_ENTRY_DEL,
rt,
--
2.24.1
Powered by blists - more mailing lists