route.c (0ee0f47c26b2f909ec95d7d8fed8119e288c4dd3) route.c (0284696b97b2fad1b220871559dff410cc3187e0)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Linux INET6 implementation
4 * FIB front-end.
5 *
6 * Authors:
7 * Pedro Roque <roque@di.fc.ul.pt>
8 */

--- 3735 unchanged lines hidden (view full) ---

3744
3745 if (rt == net->ipv6.fib6_null_entry)
3746 goto out_put;
3747 table = rt->fib6_table;
3748 spin_lock_bh(&table->tb6_lock);
3749
3750 if (rt->fib6_nsiblings && cfg->fc_delete_all_nh) {
3751 struct fib6_info *sibling, *next_sibling;
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Linux INET6 implementation
4 * FIB front-end.
5 *
6 * Authors:
7 * Pedro Roque <roque@di.fc.ul.pt>
8 */

--- 3735 unchanged lines hidden (view full) ---

3744
3745 if (rt == net->ipv6.fib6_null_entry)
3746 goto out_put;
3747 table = rt->fib6_table;
3748 spin_lock_bh(&table->tb6_lock);
3749
3750 if (rt->fib6_nsiblings && cfg->fc_delete_all_nh) {
3751 struct fib6_info *sibling, *next_sibling;
3752 struct fib6_node *fn;
3752
3753 /* prefer to send a single notification with all hops */
3754 skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any());
3755 if (skb) {
3756 u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
3757
3758 if (rt6_fill_node(net, skb, rt, NULL,
3759 NULL, NULL, 0, RTM_DELROUTE,
3760 info->portid, seq, 0) < 0) {
3761 kfree_skb(skb);
3762 skb = NULL;
3763 } else
3764 info->skip_notify = 1;
3765 }
3766
3753
3754 /* prefer to send a single notification with all hops */
3755 skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any());
3756 if (skb) {
3757 u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
3758
3759 if (rt6_fill_node(net, skb, rt, NULL,
3760 NULL, NULL, 0, RTM_DELROUTE,
3761 info->portid, seq, 0) < 0) {
3762 kfree_skb(skb);
3763 skb = NULL;
3764 } else
3765 info->skip_notify = 1;
3766 }
3767
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 */
3767 info->skip_notify_kernel = 1;
3773 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 }
3768 call_fib6_multipath_entry_notifiers(net,
3769 FIB_EVENT_ENTRY_DEL,
3770 rt,
3771 rt->fib6_nsiblings,
3772 NULL);
3773 list_for_each_entry_safe(sibling, next_sibling,
3774 &rt->fib6_siblings,
3775 fib6_siblings) {

--- 2699 unchanged lines hidden ---
3794 call_fib6_multipath_entry_notifiers(net,
3795 FIB_EVENT_ENTRY_DEL,
3796 rt,
3797 rt->fib6_nsiblings,
3798 NULL);
3799 list_for_each_entry_safe(sibling, next_sibling,
3800 &rt->fib6_siblings,
3801 fib6_siblings) {

--- 2699 unchanged lines hidden ---