Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f4fe759 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ipv6-followup-to-fib6_info-change'



David Ahern says:

====================
net/ipv6: followup to fib6_info change

Followup to fib change for IPv6.

First 2 patches rename fib6_info struct elements to match its name,
and rename addrconf_dst_alloc to match what it returns.

Patches 3-7 refactor the code to remove the need for fib6_idev reducing
fib6_info by another 8 bytes to 200 bytes.

Patch 8 fixes the gfp flags argument to addrconf_prefix_route in a
couple of places.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 88078d98 27b10608
Loading
Loading
Loading
Loading
+28 −28
Original line number Diff line number Diff line
@@ -4705,17 +4705,17 @@ static bool mlxsw_sp_fib6_rt_should_ignore(const struct fib6_info *rt)
	 * are trapped to the CPU, so no need to program specific routes
	 * for them.
	 */
	if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_LINKLOCAL)
	if (ipv6_addr_type(&rt->fib6_dst.addr) & IPV6_ADDR_LINKLOCAL)
		return true;

	/* Multicast routes aren't supported, so ignore them. Neighbour
	 * Discovery packets are specifically trapped.
	 */
	if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_MULTICAST)
	if (ipv6_addr_type(&rt->fib6_dst.addr) & IPV6_ADDR_MULTICAST)
		return true;

	/* Cloned routes are irrelevant in the forwarding path. */
	if (rt->rt6i_flags & RTF_CACHE)
	if (rt->fib6_flags & RTF_CACHE)
		return true;

	return false;
@@ -4759,7 +4759,7 @@ static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
static bool mlxsw_sp_fib6_rt_can_mp(const struct fib6_info *rt)
{
	/* RTF_CACHE routes are ignored */
	return (rt->rt6i_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY;
	return (rt->fib6_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY;
}

static struct fib6_info *
@@ -4784,16 +4784,16 @@ mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
		/* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same
		 * virtual router.
		 */
		if (rt->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id)
		if (rt->fib6_table->tb6_id > nrt->fib6_table->tb6_id)
			continue;
		if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id)
		if (rt->fib6_table->tb6_id != nrt->fib6_table->tb6_id)
			break;
		if (rt->rt6i_metric < nrt->rt6i_metric)
		if (rt->fib6_metric < nrt->fib6_metric)
			continue;
		if (rt->rt6i_metric == nrt->rt6i_metric &&
		if (rt->fib6_metric == nrt->fib6_metric &&
		    mlxsw_sp_fib6_rt_can_mp(rt))
			return fib6_entry;
		if (rt->rt6i_metric > nrt->rt6i_metric)
		if (rt->fib6_metric > nrt->fib6_metric)
			break;
	}

@@ -4899,7 +4899,7 @@ static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp,
				    const struct fib6_info *rt)
{
	return rt->rt6i_flags & RTF_GATEWAY ||
	return rt->fib6_flags & RTF_GATEWAY ||
	       mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
}

@@ -5092,9 +5092,9 @@ static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
	 * local, which will cause them to be trapped with a lower
	 * priority than packets that need to be locally received.
	 */
	if (rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST))
	if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST))
		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
	else if (rt->rt6i_flags & RTF_REJECT)
	else if (rt->fib6_flags & RTF_REJECT)
		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
	else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt))
		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
@@ -5175,18 +5175,18 @@ mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
	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->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id)
		if (rt->fib6_table->tb6_id > nrt->fib6_table->tb6_id)
			continue;
		if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id)
		if (rt->fib6_table->tb6_id != nrt->fib6_table->tb6_id)
			break;
		if (replace && rt->rt6i_metric == nrt->rt6i_metric) {
		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->rt6i_metric > nrt->rt6i_metric)
		if (rt->fib6_metric > nrt->fib6_metric)
			return fallback ?: fib6_entry;
	}

@@ -5215,7 +5215,7 @@ mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry *new6_entry,
		list_for_each_entry(last, &fib_node->entry_list, common.list) {
			struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(last);

			if (nrt->rt6i_table->tb6_id > rt->rt6i_table->tb6_id)
			if (nrt->fib6_table->tb6_id > rt->fib6_table->tb6_id)
				break;
			fib6_entry = last;
		}
@@ -5275,22 +5275,22 @@ mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
	struct mlxsw_sp_fib *fib;
	struct mlxsw_sp_vr *vr;

	vr = mlxsw_sp_vr_find(mlxsw_sp, rt->rt6i_table->tb6_id);
	vr = mlxsw_sp_vr_find(mlxsw_sp, rt->fib6_table->tb6_id);
	if (!vr)
		return NULL;
	fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV6);

	fib_node = mlxsw_sp_fib_node_lookup(fib, &rt->rt6i_dst.addr,
					    sizeof(rt->rt6i_dst.addr),
					    rt->rt6i_dst.plen);
	fib_node = mlxsw_sp_fib_node_lookup(fib, &rt->fib6_dst.addr,
					    sizeof(rt->fib6_dst.addr),
					    rt->fib6_dst.plen);
	if (!fib_node)
		return NULL;

	list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
		struct fib6_info *iter_rt = mlxsw_sp_fib6_entry_rt(fib6_entry);

		if (rt->rt6i_table->tb6_id == iter_rt->rt6i_table->tb6_id &&
		    rt->rt6i_metric == iter_rt->rt6i_metric &&
		if (rt->fib6_table->tb6_id == iter_rt->fib6_table->tb6_id &&
		    rt->fib6_metric == iter_rt->fib6_metric &&
		    mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt))
			return fib6_entry;
	}
@@ -5325,16 +5325,16 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
	if (mlxsw_sp->router->aborted)
		return 0;

	if (rt->rt6i_src.plen)
	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->rt6i_table->tb6_id,
					 &rt->rt6i_dst.addr,
					 sizeof(rt->rt6i_dst.addr),
					 rt->rt6i_dst.plen,
	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);
+0 −1
Original line number Diff line number Diff line
@@ -143,7 +143,6 @@ struct ipv6_ac_socklist {

struct ifacaddr6 {
	struct in6_addr		aca_addr;
	struct inet6_dev	*aca_idev;
	struct fib6_info	*aca_rt;
	struct ifacaddr6	*aca_next;
	int			aca_users;
+23 −19
Original line number Diff line number Diff line
@@ -134,34 +134,33 @@ struct fib6_nh {
};

struct fib6_info {
	struct fib6_table		*rt6i_table;
	struct fib6_table		*fib6_table;
	struct fib6_info __rcu		*rt6_next;
	struct fib6_node __rcu		*rt6i_node;
	struct fib6_node __rcu		*fib6_node;

	/* Multipath routes:
	 * siblings is a list of fib6_info that have the the same metric/weight,
	 * destination, but not the same gateway. nsiblings is just a cache
	 * to speed up lookup.
	 */
	struct list_head		rt6i_siblings;
	unsigned int			rt6i_nsiblings;
	struct list_head		fib6_siblings;
	unsigned int			fib6_nsiblings;

	atomic_t			rt6i_ref;
	struct inet6_dev		*rt6i_idev;
	atomic_t			fib6_ref;
	unsigned long			expires;
	struct dst_metrics		*fib6_metrics;
#define fib6_pmtu		fib6_metrics->metrics[RTAX_MTU-1]

	struct rt6key			rt6i_dst;
	u32				rt6i_flags;
	struct rt6key			rt6i_src;
	struct rt6key			rt6i_prefsrc;
	struct rt6key			fib6_dst;
	u32				fib6_flags;
	struct rt6key			fib6_src;
	struct rt6key			fib6_prefsrc;

	struct rt6_info * __percpu	*rt6i_pcpu;
	struct rt6_exception_bucket __rcu *rt6i_exception_bucket;

	u32				rt6i_metric;
	u8				rt6i_protocol;
	u32				fib6_metric;
	u8				fib6_protocol;
	u8				fib6_type;
	u8				exception_bucket_flushed:1,
					should_flush:1,
@@ -206,7 +205,7 @@ static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)

static inline void fib6_clean_expires(struct fib6_info *f6i)
{
	f6i->rt6i_flags &= ~RTF_EXPIRES;
	f6i->fib6_flags &= ~RTF_EXPIRES;
	f6i->expires = 0;
}

@@ -214,12 +213,12 @@ static inline void fib6_set_expires(struct fib6_info *f6i,
				    unsigned long expires)
{
	f6i->expires = expires;
	f6i->rt6i_flags |= RTF_EXPIRES;
	f6i->fib6_flags |= RTF_EXPIRES;
}

static inline bool fib6_check_expired(const struct fib6_info *f6i)
{
	if (f6i->rt6i_flags & RTF_EXPIRES)
	if (f6i->fib6_flags & RTF_EXPIRES)
		return time_after(jiffies, f6i->expires);
	return false;
}
@@ -250,14 +249,14 @@ static inline void rt6_update_expires(struct rt6_info *rt0, int timeout)
 * Return true if we can get cookie safely
 * Return false if not
 */
static inline bool rt6_get_cookie_safe(const struct fib6_info *rt,
static inline bool rt6_get_cookie_safe(const struct fib6_info *f6i,
				       u32 *cookie)
{
	struct fib6_node *fn;
	bool status = false;

	rcu_read_lock();
	fn = rcu_dereference(rt->rt6i_node);
	fn = rcu_dereference(f6i->fib6_node);

	if (fn) {
		*cookie = fn->fn_sernum;
@@ -295,12 +294,12 @@ void fib6_info_destroy(struct fib6_info *f6i);

static inline void fib6_info_hold(struct fib6_info *f6i)
{
	atomic_inc(&f6i->rt6i_ref);
	atomic_inc(&f6i->fib6_ref);
}

static inline void fib6_info_release(struct fib6_info *f6i)
{
	if (f6i && atomic_dec_and_test(&f6i->rt6i_ref))
	if (f6i && atomic_dec_and_test(&f6i->fib6_ref))
		fib6_info_destroy(f6i);
}

@@ -410,6 +409,11 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
	     struct nl_info *info, struct netlink_ext_ack *extack);
int fib6_del(struct fib6_info *rt, struct nl_info *info);

static inline struct net_device *fib6_info_nh_dev(const struct fib6_info *f6i)
{
	return f6i->fib6_nh.nh_dev;
}

void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
		     unsigned int flags);

+17 −17
Original line number Diff line number Diff line
@@ -66,9 +66,9 @@ static inline bool rt6_need_strict(const struct in6_addr *daddr)
		(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
}

static inline bool rt6_qualify_for_ecmp(const struct fib6_info *rt)
static inline bool rt6_qualify_for_ecmp(const struct fib6_info *f6i)
{
	return (rt->rt6i_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) ==
	return (f6i->fib6_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) ==
	       RTF_GATEWAY;
}

@@ -102,26 +102,27 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg);

int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags,
		  struct netlink_ext_ack *extack);
int ip6_ins_rt(struct net *net, struct fib6_info *rt);
int ip6_del_rt(struct net *net, struct fib6_info *rt);
int ip6_ins_rt(struct net *net, struct fib6_info *f6i);
int ip6_del_rt(struct net *net, struct fib6_info *f6i);

void rt6_flush_exceptions(struct fib6_info *rt);
void rt6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args,
void rt6_flush_exceptions(struct fib6_info *f6i);
void rt6_age_exceptions(struct fib6_info *f6i, struct fib6_gc_args *gc_args,
			unsigned long now);

static inline int ip6_route_get_saddr(struct net *net, struct fib6_info *rt,
static inline int ip6_route_get_saddr(struct net *net, struct fib6_info *f6i,
				      const struct in6_addr *daddr,
				      unsigned int prefs,
				      struct in6_addr *saddr)
{
	struct inet6_dev *idev = rt ? rt->rt6i_idev : NULL;
	int err = 0;

	if (rt && rt->rt6i_prefsrc.plen)
		*saddr = rt->rt6i_prefsrc.addr;
	else
		err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
					 daddr, prefs, saddr);
	if (f6i && f6i->fib6_prefsrc.plen) {
		*saddr = f6i->fib6_prefsrc.addr;
	} else {
		struct net_device *dev = f6i ? fib6_info_nh_dev(f6i) : NULL;

		err = ipv6_dev_get_saddr(net, dev, daddr, prefs, saddr);
	}

	return err;
}
@@ -136,7 +137,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, struct flowi6 *fl6);

void fib6_force_start_gc(struct net *net);

struct fib6_info *addrconf_dst_alloc(struct net *net, struct inet6_dev *idev,
struct fib6_info *addrconf_f6i_alloc(struct net *net, struct inet6_dev *idev,
				     const struct in6_addr *addr, bool anycast,
				     gfp_t gfp_flags);

@@ -176,14 +177,14 @@ struct rt6_rtnl_dump_arg {
	struct net *net;
};

int rt6_dump_route(struct fib6_info *rt, void *p_arg);
int rt6_dump_route(struct fib6_info *f6i, void *p_arg);
void rt6_mtu_change(struct net_device *dev, unsigned int mtu);
void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
void rt6_clean_tohost(struct net *net, struct in6_addr *gateway);
void rt6_sync_up(struct net_device *dev, unsigned int nh_flags);
void rt6_disable_ip(struct net_device *dev, unsigned long event);
void rt6_sync_down_dev(struct net_device *dev, unsigned long event);
void rt6_multipath_rebalance(struct fib6_info *rt);
void rt6_multipath_rebalance(struct fib6_info *f6i);

void rt6_uncached_list_add(struct rt6_info *rt);
void rt6_uncached_list_del(struct rt6_info *rt);
@@ -274,7 +275,6 @@ static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt,
static inline bool rt6_duplicate_nexthop(struct fib6_info *a, struct fib6_info *b)
{
	return a->fib6_nh.nh_dev == b->fib6_nh.nh_dev &&
	       a->rt6i_idev == b->rt6i_idev &&
	       ipv6_addr_equal(&a->fib6_nh.nh_gw, &b->fib6_nh.nh_gw) &&
	       !lwtunnel_cmp_encap(a->fib6_nh.nh_lwtstate, b->fib6_nh.nh_lwtstate);
}
+30 −29
Original line number Diff line number Diff line
@@ -994,7 +994,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
	gfp_t gfp_flags = can_block ? GFP_KERNEL : GFP_ATOMIC;
	struct net *net = dev_net(idev->dev);
	struct inet6_ifaddr *ifa = NULL;
	struct fib6_info *rt = NULL;
	struct fib6_info *f6i = NULL;
	int err = 0;
	int addr_type = ipv6_addr_type(addr);

@@ -1036,16 +1036,16 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
		goto out;
	}

	rt = addrconf_dst_alloc(net, idev, addr, false, gfp_flags);
	if (IS_ERR(rt)) {
		err = PTR_ERR(rt);
		rt = NULL;
	f6i = addrconf_f6i_alloc(net, idev, addr, false, gfp_flags);
	if (IS_ERR(f6i)) {
		err = PTR_ERR(f6i);
		f6i = NULL;
		goto out;
	}

	if (net->ipv6.devconf_all->disable_policy ||
	    idev->cnf.disable_policy)
		rt->dst_nopolicy = true;
		f6i->dst_nopolicy = true;

	neigh_parms_data_state_setall(idev->nd_parms);

@@ -1067,7 +1067,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
	ifa->cstamp = ifa->tstamp = jiffies;
	ifa->tokenized = false;

	ifa->rt = rt;
	ifa->rt = f6i;

	ifa->idev = idev;
	in6_dev_hold(idev);
@@ -1101,7 +1101,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
	inet6addr_notifier_call_chain(NETDEV_UP, ifa);
out:
	if (unlikely(err < 0)) {
		fib6_info_release(rt);
		fib6_info_release(f6i);

		if (ifa) {
			if (ifa->idev)
@@ -1178,19 +1178,19 @@ check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires)
static void
cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires, bool del_rt)
{
	struct fib6_info *rt;
	struct fib6_info *f6i;

	rt = addrconf_get_prefix_route(&ifp->addr,
	f6i = addrconf_get_prefix_route(&ifp->addr,
				       ifp->prefix_len,
				       ifp->idev->dev,
				       0, RTF_GATEWAY | RTF_DEFAULT);
	if (rt) {
	if (f6i) {
		if (del_rt)
			ip6_del_rt(dev_net(ifp->idev->dev), rt);
			ip6_del_rt(dev_net(ifp->idev->dev), f6i);
		else {
			if (!(rt->rt6i_flags & RTF_EXPIRES))
				fib6_set_expires(rt, expires);
			fib6_info_release(rt);
			if (!(f6i->fib6_flags & RTF_EXPIRES))
				fib6_set_expires(f6i, expires);
			fib6_info_release(f6i);
		}
	}
}
@@ -2370,9 +2370,9 @@ static struct fib6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
	for_each_fib6_node_rt_rcu(fn) {
		if (rt->fib6_nh.nh_dev->ifindex != dev->ifindex)
			continue;
		if ((rt->rt6i_flags & flags) != flags)
		if ((rt->fib6_flags & flags) != flags)
			continue;
		if ((rt->rt6i_flags & noflags) != 0)
		if ((rt->fib6_flags & noflags) != 0)
			continue;
		fib6_info_hold(rt);
		break;
@@ -3245,7 +3245,7 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
			addrconf_add_linklocal(idev, &addr, 0);
		else if (prefix_route)
			addrconf_prefix_route(&addr, 64, idev->dev,
					      0, 0, GFP_ATOMIC);
					      0, 0, GFP_KERNEL);
		break;
	case IN6_ADDR_GEN_MODE_NONE:
	default:
@@ -3341,22 +3341,22 @@ static int fixup_permanent_addr(struct net *net,
				struct inet6_dev *idev,
				struct inet6_ifaddr *ifp)
{
	/* !rt6i_node means the host route was removed from the
	/* !fib6_node means the host route was removed from the
	 * FIB, for example, if 'lo' device is taken down. In that
	 * case regenerate the host route.
	 */
	if (!ifp->rt || !ifp->rt->rt6i_node) {
		struct fib6_info *rt, *prev;
	if (!ifp->rt || !ifp->rt->fib6_node) {
		struct fib6_info *f6i, *prev;

		rt = addrconf_dst_alloc(net, idev, &ifp->addr, false,
		f6i = addrconf_f6i_alloc(net, idev, &ifp->addr, false,
					 GFP_ATOMIC);
		if (IS_ERR(rt))
			return PTR_ERR(rt);
		if (IS_ERR(f6i))
			return PTR_ERR(f6i);

		/* ifp->rt can be accessed outside of rtnl */
		spin_lock(&ifp->lock);
		prev = ifp->rt;
		ifp->rt = rt;
		ifp->rt = f6i;
		spin_unlock(&ifp->lock);

		fib6_info_release(prev);
@@ -4817,9 +4817,10 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
				u32 portid, u32 seq, int event, unsigned int flags)
{
	struct net_device *dev = fib6_info_nh_dev(ifaca->aca_rt);
	int ifindex = dev ? dev->ifindex : 1;
	struct nlmsghdr  *nlh;
	u8 scope = RT_SCOPE_UNIVERSE;
	int ifindex = ifaca->aca_idev->dev->ifindex;

	if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE)
		scope = RT_SCOPE_SITE;
@@ -5612,14 +5613,14 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
		 * our DAD process, so we don't need
		 * to do it again
		 */
		if (!rcu_access_pointer(ifp->rt->rt6i_node))
		if (!rcu_access_pointer(ifp->rt->fib6_node))
			ip6_ins_rt(net, ifp->rt);
		if (ifp->idev->cnf.forwarding)
			addrconf_join_anycast(ifp);
		if (!ipv6_addr_any(&ifp->peer_addr))
			addrconf_prefix_route(&ifp->peer_addr, 128,
					      ifp->idev->dev, 0, 0,
					      GFP_KERNEL);
					      GFP_ATOMIC);
		break;
	case RTM_DELADDR:
		if (ifp->idev->cnf.forwarding)
Loading