netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups
@ 2019-04-16 21:35 David Ahern
  2019-04-16 21:35 ` [PATCH v2 net-next 01/13] ipv6: Rename fib6_multipath_select and pass fib6_result David Ahern
                   ` (13 more replies)
  0 siblings, 14 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:35 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Add fib6_result as a single data structure to hold results from a fib
lookup. IPv6 currently has everything in 1 data structure - a fib6_info,
but with nexthop objects the fib6_nh can be in a nexthop or a nexthop
can be a blackhole which affects the fib6_type and flags (REJECT).

v2
- fixed 2 bugs in patch12:
  i. checking return from fib6_table_lookup in fib6_lookup
  ii. call to fib6_rule_saddr in fib6_rule_action_alt should use res->nh

David Ahern (13):
  ipv6: Rename fib6_multipath_select and pass fib6_result
  ipv6: Pass fib6_result to rt6_find_cached_rt
  ipv6: Pass fib6_result to ip6_rt_cache_alloc
  ipv6: Pass fib6_result to ip6_create_rt_rcu
  ipv6: Pass fib6_result to pcpu route functions
  ipv6: Pass fib6_result to ip6_rt_get_dev_rcu and ip6_rt_copy_init
  ipv6: Pass fib6_result to rt6_insert_exception
  ipv6: Pass fib6_result to ip6_mtu_from_fib6 and fib6_mtu
  ipv6: Pass fib6_result to rt6_device_match
  ipv6: Pass fib6_result to rt6_select and find_rr_leaf
  ipv6: Pass fib6_result to fib6_table_lookup tracepoint
  ipv6: Pass fib6_result to fib lookups
  ipv6: Add fib6_type and fib6_flags to fib6_result

 include/net/ip6_fib.h       |  24 ++-
 include/net/ip6_route.h     |   5 +-
 include/net/ipv6_stubs.h    |  25 ++-
 include/trace/events/fib6.h |  16 +-
 net/core/filter.c           |  56 +++---
 net/ipv6/addrconf_core.c    |  29 +--
 net/ipv6/af_inet6.c         |   2 +-
 net/ipv6/fib6_rules.c       |  34 ++--
 net/ipv6/ip6_fib.c          |   7 +-
 net/ipv6/route.c            | 443 +++++++++++++++++++++++++-------------------
 10 files changed, 348 insertions(+), 293 deletions(-)

-- 
2.11.0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 01/13] ipv6: Rename fib6_multipath_select and pass fib6_result
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
@ 2019-04-16 21:35 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 02/13] ipv6: Pass fib6_result to rt6_find_cached_rt David Ahern
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:35 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Add 'struct fib6_result' to hold the fib entry and fib6_nh from a fib
lookup as separate entries, similar to what IPv4 now has with fib_result.

Rename fib6_multipath_select to fib6_select_path, pass fib6_result to
it, and set f6i and nh in the result once a path selection is done.
Call fib6_select_path unconditionally for path selection which means
moving the sibling and oif check to fib6_select_path. To handle the two
different call paths (2 only call multipath_select if flowi6_oif == 0 and
the other always calls it), add a new have_oif_match that controls the
sibling walk if relevant.

Update callers of fib6_multipath_select accordingly and have them use the
fib6_info and fib6_nh from the result.

This is needed for multipath nexthop objects where a single f6i can
point to multiple fib6_nh (similar to IPv4).

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/ip6_fib.h    | 13 ++++++----
 include/net/ipv6_stubs.h |  9 +++----
 net/core/filter.c        | 34 +++++++++++++-------------
 net/ipv6/addrconf_core.c | 11 ++++-----
 net/ipv6/af_inet6.c      |  2 +-
 net/ipv6/route.c         | 63 +++++++++++++++++++++++++-----------------------
 6 files changed, 68 insertions(+), 64 deletions(-)

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 2e9235adfa0d..c4d818041663 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -190,6 +190,11 @@ struct rt6_info {
 	unsigned short			rt6i_nfheader_len;
 };
 
+struct fib6_result {
+	struct fib6_nh		*nh;
+	struct fib6_info	*f6i;
+};
+
 #define for_each_fib6_node_rt_rcu(fn)					\
 	for (rt = rcu_dereference((fn)->leaf); rt;			\
 	     rt = rcu_dereference(rt->fib6_next))
@@ -391,11 +396,9 @@ struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
 struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
 				    int oif, struct flowi6 *fl6, int strict);
 
-struct fib6_info *fib6_multipath_select(const struct net *net,
-					struct fib6_info *match,
-					struct flowi6 *fl6, int oif,
-					const struct sk_buff *skb, int strict);
-
+void fib6_select_path(const struct net *net, struct fib6_result *res,
+		      struct flowi6 *fl6, int oif, bool have_oif_match,
+		      const struct sk_buff *skb, int strict);
 struct fib6_node *fib6_node_lookup(struct fib6_node *root,
 				   const struct in6_addr *daddr,
 				   const struct in6_addr *saddr);
diff --git a/include/net/ipv6_stubs.h b/include/net/ipv6_stubs.h
index 453b55bf6723..5df36d6a2613 100644
--- a/include/net/ipv6_stubs.h
+++ b/include/net/ipv6_stubs.h
@@ -14,6 +14,7 @@
 struct fib6_info;
 struct fib6_nh;
 struct fib6_config;
+struct fib6_result;
 
 /* This is ugly, ideally these symbols should be built
  * into the core kernel.
@@ -34,11 +35,9 @@ struct ipv6_stub {
 					      struct fib6_table *table,
 					      int oif, struct flowi6 *fl6,
 					      int flags);
-	struct fib6_info *(*fib6_multipath_select)(const struct net *net,
-						   struct fib6_info *f6i,
-						   struct flowi6 *fl6, int oif,
-						   const struct sk_buff *skb,
-						   int strict);
+	void (*fib6_select_path)(const struct net *net, struct fib6_result *res,
+				 struct flowi6 *fl6, int oif, bool oif_match,
+				 const struct sk_buff *skb, int strict);
 	u32 (*ip6_mtu_from_fib6)(struct fib6_info *f6i, struct in6_addr *daddr,
 				 struct in6_addr *saddr);
 
diff --git a/net/core/filter.c b/net/core/filter.c
index 95a27fdf9a40..72b29e4d705b 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4677,9 +4677,9 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
 	struct in6_addr *src = (struct in6_addr *) params->ipv6_src;
 	struct in6_addr *dst = (struct in6_addr *) params->ipv6_dst;
 	struct neighbour *neigh;
+	struct fib6_result res;
 	struct net_device *dev;
 	struct inet6_dev *idev;
-	struct fib6_info *f6i;
 	struct flowi6 fl6;
 	int strict = 0;
 	int oif;
@@ -4724,21 +4724,23 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
 		if (unlikely(!tb))
 			return BPF_FIB_LKUP_RET_NOT_FWDED;
 
-		f6i = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6, strict);
+		res.f6i = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6,
+						       strict);
 	} else {
 		fl6.flowi6_mark = 0;
 		fl6.flowi6_secid = 0;
 		fl6.flowi6_tun_key.tun_id = 0;
 		fl6.flowi6_uid = sock_net_uid(net, NULL);
 
-		f6i = ipv6_stub->fib6_lookup(net, oif, &fl6, strict);
+		res.f6i = ipv6_stub->fib6_lookup(net, oif, &fl6, strict);
 	}
 
-	if (unlikely(IS_ERR_OR_NULL(f6i) || f6i == net->ipv6.fib6_null_entry))
+	if (unlikely(IS_ERR_OR_NULL(res.f6i) ||
+		     res.f6i == net->ipv6.fib6_null_entry))
 		return BPF_FIB_LKUP_RET_NOT_FWDED;
 
-	if (unlikely(f6i->fib6_flags & RTF_REJECT)) {
-		switch (f6i->fib6_type) {
+	if (unlikely(res.f6i->fib6_flags & RTF_REJECT)) {
+		switch (res.f6i->fib6_type) {
 		case RTN_BLACKHOLE:
 			return BPF_FIB_LKUP_RET_BLACKHOLE;
 		case RTN_UNREACHABLE:
@@ -4750,28 +4752,26 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
 		}
 	}
 
-	if (f6i->fib6_type != RTN_UNICAST)
+	if (res.f6i->fib6_type != RTN_UNICAST)
 		return BPF_FIB_LKUP_RET_NOT_FWDED;
 
-	if (f6i->fib6_nsiblings && fl6.flowi6_oif == 0)
-		f6i = ipv6_stub->fib6_multipath_select(net, f6i, &fl6,
-						       fl6.flowi6_oif, NULL,
-						       strict);
+	ipv6_stub->fib6_select_path(net, &res, &fl6, fl6.flowi6_oif,
+				    fl6.flowi6_oif != 0, NULL, strict);
 
 	if (check_mtu) {
-		mtu = ipv6_stub->ip6_mtu_from_fib6(f6i, dst, src);
+		mtu = ipv6_stub->ip6_mtu_from_fib6(res.f6i, dst, src);
 		if (params->tot_len > mtu)
 			return BPF_FIB_LKUP_RET_FRAG_NEEDED;
 	}
 
-	if (f6i->fib6_nh.fib_nh_lws)
+	if (res.nh->fib_nh_lws)
 		return BPF_FIB_LKUP_RET_UNSUPP_LWT;
 
-	if (f6i->fib6_nh.fib_nh_gw_family)
-		*dst = f6i->fib6_nh.fib_nh_gw6;
+	if (res.nh->fib_nh_gw_family)
+		*dst = res.nh->fib_nh_gw6;
 
-	dev = f6i->fib6_nh.fib_nh_dev;
-	params->rt_metric = f6i->fib6_metric;
+	dev = res.nh->fib_nh_dev;
+	params->rt_metric = res.f6i->fib6_metric;
 
 	/* xdp and cls_bpf programs are run in RCU-bh so rcu_read_lock_bh is
 	 * not needed here.
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index e37e4c5871f7..b11fa0aa18a0 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -158,12 +158,11 @@ eafnosupport_fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
 	return NULL;
 }
 
-static struct fib6_info *
-eafnosupport_fib6_multipath_select(const struct net *net, struct fib6_info *f6i,
-				   struct flowi6 *fl6, int oif,
-				   const struct sk_buff *skb, int strict)
+static void
+eafnosupport_fib6_select_path(const struct net *net, struct fib6_result *res,
+			      struct flowi6 *fl6, int oif, bool have_oif_match,
+			      const struct sk_buff *skb, int strict)
 {
-	return f6i;
 }
 
 static u32
@@ -187,7 +186,7 @@ const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
 	.fib6_get_table    = eafnosupport_fib6_get_table,
 	.fib6_table_lookup = eafnosupport_fib6_table_lookup,
 	.fib6_lookup       = eafnosupport_fib6_lookup,
-	.fib6_multipath_select = eafnosupport_fib6_multipath_select,
+	.fib6_select_path  = eafnosupport_fib6_select_path,
 	.ip6_mtu_from_fib6 = eafnosupport_ip6_mtu_from_fib6,
 	.fib6_nh_init	   = eafnosupport_fib6_nh_init,
 };
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 1dac6ea6666a..d8587ca4fbeb 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -917,7 +917,7 @@ static const struct ipv6_stub ipv6_stub_impl = {
 	.fib6_get_table	   = fib6_get_table,
 	.fib6_table_lookup = fib6_table_lookup,
 	.fib6_lookup       = fib6_lookup,
-	.fib6_multipath_select = fib6_multipath_select,
+	.fib6_select_path  = fib6_select_path,
 	.ip6_mtu_from_fib6 = ip6_mtu_from_fib6,
 	.fib6_nh_init	   = fib6_nh_init,
 	.fib6_nh_release   = fib6_nh_release,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index a77c004d67fb..dd717d1539b6 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -428,13 +428,15 @@ static bool rt6_check_expired(const struct rt6_info *rt)
 	return false;
 }
 
-struct fib6_info *fib6_multipath_select(const struct net *net,
-					struct fib6_info *match,
-					struct flowi6 *fl6, int oif,
-					const struct sk_buff *skb,
-					int strict)
+void fib6_select_path(const struct net *net, struct fib6_result *res,
+		      struct flowi6 *fl6, int oif, bool have_oif_match,
+		      const struct sk_buff *skb, int strict)
 {
 	struct fib6_info *sibling, *next_sibling;
+	struct fib6_info *match = res->f6i;
+
+	if (!match->fib6_nsiblings || have_oif_match)
+		goto out;
 
 	/* We might have already computed the hash for ICMPv6 errors. In such
 	 * case it will always be non-zero. Otherwise now is the time to do it.
@@ -443,7 +445,7 @@ struct fib6_info *fib6_multipath_select(const struct net *net,
 		fl6->mp_hash = rt6_multipath_hash(net, fl6, skb, NULL);
 
 	if (fl6->mp_hash <= atomic_read(&match->fib6_nh.fib_nh_upper_bound))
-		return match;
+		goto out;
 
 	list_for_each_entry_safe(sibling, next_sibling, &match->fib6_siblings,
 				 fib6_siblings) {
@@ -459,7 +461,9 @@ struct fib6_info *fib6_multipath_select(const struct net *net,
 		break;
 	}
 
-	return match;
+out:
+	res->f6i = match;
+	res->nh = &match->fib6_nh;
 }
 
 /*
@@ -1063,7 +1067,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 					     const struct sk_buff *skb,
 					     int flags)
 {
-	struct fib6_info *f6i;
+	struct fib6_result res = {};
 	struct fib6_node *fn;
 	struct rt6_info *rt;
 
@@ -1073,14 +1077,14 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 	rcu_read_lock();
 	fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
 restart:
-	f6i = rcu_dereference(fn->leaf);
-	if (!f6i)
-		f6i = net->ipv6.fib6_null_entry;
+	res.f6i = rcu_dereference(fn->leaf);
+	if (!res.f6i)
+		res.f6i = net->ipv6.fib6_null_entry;
 	else
-		f6i = rt6_device_match(net, f6i, &fl6->saddr,
-				      fl6->flowi6_oif, flags);
+		res.f6i = rt6_device_match(net, res.f6i, &fl6->saddr,
+					   fl6->flowi6_oif, flags);
 
-	if (f6i == net->ipv6.fib6_null_entry) {
+	if (res.f6i == net->ipv6.fib6_null_entry) {
 		fn = fib6_backtrack(fn, &fl6->saddr);
 		if (fn)
 			goto restart;
@@ -1090,20 +1094,20 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 		goto out;
 	}
 
-	if (f6i->fib6_nsiblings && fl6->flowi6_oif == 0)
-		f6i = fib6_multipath_select(net, f6i, fl6, fl6->flowi6_oif, skb,
-					    flags);
+	fib6_select_path(net, &res, fl6, fl6->flowi6_oif,
+			 fl6->flowi6_oif != 0, skb, flags);
+
 	/* Search through exception table */
-	rt = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr);
+	rt = rt6_find_cached_rt(res.f6i, &fl6->daddr, &fl6->saddr);
 	if (rt) {
 		if (ip6_hold_safe(net, &rt))
 			dst_use_noref(&rt->dst, jiffies);
 	} else {
-		rt = ip6_create_rt_rcu(f6i);
+		rt = ip6_create_rt_rcu(res.f6i);
 	}
 
 out:
-	trace_fib6_table_lookup(net, f6i, table, fl6);
+	trace_fib6_table_lookup(net, res.f6i, table, fl6);
 
 	rcu_read_unlock();
 
@@ -1843,7 +1847,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 			       int oif, struct flowi6 *fl6,
 			       const struct sk_buff *skb, int flags)
 {
-	struct fib6_info *f6i;
+	struct fib6_result res = {};
 	struct rt6_info *rt;
 	int strict = 0;
 
@@ -1854,19 +1858,18 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 
 	rcu_read_lock();
 
-	f6i = fib6_table_lookup(net, table, oif, fl6, strict);
-	if (f6i == net->ipv6.fib6_null_entry) {
+	res.f6i = fib6_table_lookup(net, table, oif, fl6, strict);
+	if (res.f6i == net->ipv6.fib6_null_entry) {
 		rt = net->ipv6.ip6_null_entry;
 		rcu_read_unlock();
 		dst_hold(&rt->dst);
 		return rt;
 	}
 
-	if (f6i->fib6_nsiblings)
-		f6i = fib6_multipath_select(net, f6i, fl6, oif, skb, strict);
+	fib6_select_path(net, &res, fl6, oif, false, skb, strict);
 
 	/*Search through exception table */
-	rt = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr);
+	rt = rt6_find_cached_rt(res.f6i, &fl6->daddr, &fl6->saddr);
 	if (rt) {
 		if (ip6_hold_safe(net, &rt))
 			dst_use_noref(&rt->dst, jiffies);
@@ -1874,7 +1877,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 		rcu_read_unlock();
 		return rt;
 	} else if (unlikely((fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH) &&
-			    !f6i->fib6_nh.fib_nh_gw_family)) {
+			    !res.nh->fib_nh_gw_family)) {
 		/* Create a RTF_CACHE clone which will not be
 		 * owned by the fib6 tree.  It is for the special case where
 		 * the daddr in the skb during the neighbor look-up is different
@@ -1882,7 +1885,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 		 */
 		struct rt6_info *uncached_rt;
 
-		uncached_rt = ip6_rt_cache_alloc(f6i, &fl6->daddr, NULL);
+		uncached_rt = ip6_rt_cache_alloc(res.f6i, &fl6->daddr, NULL);
 
 		rcu_read_unlock();
 
@@ -1904,10 +1907,10 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 		struct rt6_info *pcpu_rt;
 
 		local_bh_disable();
-		pcpu_rt = rt6_get_pcpu_route(f6i);
+		pcpu_rt = rt6_get_pcpu_route(res.f6i);
 
 		if (!pcpu_rt)
-			pcpu_rt = rt6_make_pcpu_route(net, f6i);
+			pcpu_rt = rt6_make_pcpu_route(net, res.f6i);
 
 		local_bh_enable();
 		rcu_read_unlock();
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 02/13] ipv6: Pass fib6_result to rt6_find_cached_rt
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
  2019-04-16 21:35 ` [PATCH v2 net-next 01/13] ipv6: Rename fib6_multipath_select and pass fib6_result David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 03/13] ipv6: Pass fib6_result to ip6_rt_cache_alloc David Ahern
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Simplify rt6_find_cached_rt for the fast path cases and pass fib6_result
to rt6_find_cached_rt. Rename the local return variable to ret to maintain
consisting with fib6_result name.

Update the comment in rt6_find_cached_rt to reference the new names in
a fib6_info vs the old name when fib entries were an rt6_info.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/route.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index dd717d1539b6..68122621e0ba 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -110,7 +110,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
 			 struct in6_addr *dest, struct in6_addr *src,
 			 int iif, int type, u32 portid, u32 seq,
 			 unsigned int flags);
-static struct rt6_info *rt6_find_cached_rt(struct fib6_info *rt,
+static struct rt6_info *rt6_find_cached_rt(const struct fib6_result *res,
 					   struct in6_addr *daddr,
 					   struct in6_addr *saddr);
 
@@ -1098,7 +1098,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 			 fl6->flowi6_oif != 0, skb, flags);
 
 	/* Search through exception table */
-	rt = rt6_find_cached_rt(res.f6i, &fl6->daddr, &fl6->saddr);
+	rt = rt6_find_cached_rt(&res, &fl6->daddr, &fl6->saddr);
 	if (rt) {
 		if (ip6_hold_safe(net, &rt))
 			dst_use_noref(&rt->dst, jiffies);
@@ -1538,33 +1538,33 @@ void rt6_flush_exceptions(struct fib6_info *rt)
 /* Find cached rt in the hash table inside passed in rt
  * Caller has to hold rcu_read_lock()
  */
-static struct rt6_info *rt6_find_cached_rt(struct fib6_info *rt,
+static struct rt6_info *rt6_find_cached_rt(const struct fib6_result *res,
 					   struct in6_addr *daddr,
 					   struct in6_addr *saddr)
 {
 	struct rt6_exception_bucket *bucket;
 	struct in6_addr *src_key = NULL;
 	struct rt6_exception *rt6_ex;
-	struct rt6_info *res = NULL;
+	struct rt6_info *ret = NULL;
 
-	bucket = rcu_dereference(rt->rt6i_exception_bucket);
+	bucket = rcu_dereference(res->f6i->rt6i_exception_bucket);
 
 #ifdef CONFIG_IPV6_SUBTREES
-	/* rt6i_src.plen != 0 indicates rt is in subtree
+	/* fib6i_src.plen != 0 indicates f6i is in subtree
 	 * and exception table is indexed by a hash of
-	 * both rt6i_dst and rt6i_src.
+	 * both fib6_dst and fib6_src.
 	 * Otherwise, the exception table is indexed by
-	 * a hash of only rt6i_dst.
+	 * a hash of only fib6_dst.
 	 */
-	if (rt->fib6_src.plen)
+	if (res->f6i->fib6_src.plen)
 		src_key = saddr;
 #endif
 	rt6_ex = __rt6_find_exception_rcu(&bucket, daddr, src_key);
 
 	if (rt6_ex && !rt6_check_expired(rt6_ex->rt6i))
-		res = rt6_ex->rt6i;
+		ret = rt6_ex->rt6i;
 
-	return res;
+	return ret;
 }
 
 /* Remove the passed in cached rt from the hash table that contains it */
@@ -1869,7 +1869,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 	fib6_select_path(net, &res, fl6, oif, false, skb, strict);
 
 	/*Search through exception table */
-	rt = rt6_find_cached_rt(res.f6i, &fl6->daddr, &fl6->saddr);
+	rt = rt6_find_cached_rt(&res, &fl6->daddr, &fl6->saddr);
 	if (rt) {
 		if (ip6_hold_safe(net, &rt))
 			dst_use_noref(&rt->dst, jiffies);
@@ -2426,9 +2426,12 @@ static bool ip6_redirect_nh_match(struct fib6_info *f6i,
 	 * is different.
 	 */
 	if (!ipv6_addr_equal(gw, &nh->fib_nh_gw6)) {
+		struct fib6_result res = {
+			.f6i = f6i,
+		};
 		struct rt6_info *rt_cache;
 
-		rt_cache = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr);
+		rt_cache = rt6_find_cached_rt(&res, &fl6->daddr, &fl6->saddr);
 		if (rt_cache &&
 		    ipv6_addr_equal(gw, &rt_cache->rt6i_gateway)) {
 			*ret = rt_cache;
@@ -3307,9 +3310,13 @@ static int ip6_route_del(struct fib6_config *cfg,
 			struct fib6_nh *nh;
 
 			if (cfg->fc_flags & RTF_CACHE) {
+				struct fib6_result res = {
+					.f6i = rt,
+				};
 				int rc;
 
-				rt_cache = rt6_find_cached_rt(rt, &cfg->fc_dst,
+				rt_cache = rt6_find_cached_rt(&res,
+							      &cfg->fc_dst,
 							      &cfg->fc_src);
 				if (rt_cache) {
 					rc = ip6_del_cached_rt(rt_cache, cfg);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 03/13] ipv6: Pass fib6_result to ip6_rt_cache_alloc
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
  2019-04-16 21:35 ` [PATCH v2 net-next 01/13] ipv6: Rename fib6_multipath_select and pass fib6_result David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 02/13] ipv6: Pass fib6_result to rt6_find_cached_rt David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 04/13] ipv6: Pass fib6_result to ip6_create_rt_rcu David Ahern
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Change ip6_rt_cache_alloc to take a fib6_result over a fib6_info.

Since ip6_rt_cache_alloc is only the caller, update the
rt6_is_gw_or_nonexthop helper to take fib6_result.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/route.c | 46 +++++++++++++++++++++++++---------------------
 1 file changed, 25 insertions(+), 21 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 68122621e0ba..f267b3060ac7 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -784,9 +784,10 @@ static struct fib6_info *rt6_select(struct net *net, struct fib6_node *fn,
 	return match ? match : net->ipv6.fib6_null_entry;
 }
 
-static bool rt6_is_gw_or_nonexthop(const struct fib6_info *rt)
+static bool rt6_is_gw_or_nonexthop(const struct fib6_result *res)
 {
-	return (rt->fib6_flags & RTF_NONEXTHOP) || rt->fib6_nh.fib_nh_gw_family;
+	return (res->f6i->fib6_flags & RTF_NONEXTHOP) ||
+	       res->nh->fib_nh_gw_family;
 }
 
 #ifdef CONFIG_IPV6_ROUTE_INFO
@@ -1174,10 +1175,11 @@ int ip6_ins_rt(struct net *net, struct fib6_info *rt)
 	return __ip6_ins_rt(rt, &info, NULL);
 }
 
-static struct rt6_info *ip6_rt_cache_alloc(struct fib6_info *ort,
+static struct rt6_info *ip6_rt_cache_alloc(const struct fib6_result *res,
 					   const struct in6_addr *daddr,
 					   const struct in6_addr *saddr)
 {
+	struct fib6_info *f6i = res->f6i;
 	struct net_device *dev;
 	struct rt6_info *rt;
 
@@ -1185,25 +1187,25 @@ static struct rt6_info *ip6_rt_cache_alloc(struct fib6_info *ort,
 	 *	Clone the route.
 	 */
 
-	if (!fib6_info_hold_safe(ort))
+	if (!fib6_info_hold_safe(f6i))
 		return NULL;
 
-	dev = ip6_rt_get_dev_rcu(ort);
+	dev = ip6_rt_get_dev_rcu(f6i);
 	rt = ip6_dst_alloc(dev_net(dev), dev, 0);
 	if (!rt) {
-		fib6_info_release(ort);
+		fib6_info_release(f6i);
 		return NULL;
 	}
 
-	ip6_rt_copy_init(rt, ort);
+	ip6_rt_copy_init(rt, res->f6i);
 	rt->rt6i_flags |= RTF_CACHE;
 	rt->dst.flags |= DST_HOST;
 	rt->rt6i_dst.addr = *daddr;
 	rt->rt6i_dst.plen = 128;
 
-	if (!rt6_is_gw_or_nonexthop(ort)) {
-		if (ort->fib6_dst.plen != 128 &&
-		    ipv6_addr_equal(&ort->fib6_dst.addr, daddr))
+	if (!rt6_is_gw_or_nonexthop(res)) {
+		if (f6i->fib6_dst.plen != 128 &&
+		    ipv6_addr_equal(&f6i->fib6_dst.addr, daddr))
 			rt->rt6i_flags |= RTF_ANYCAST;
 #ifdef CONFIG_IPV6_SUBTREES
 		if (rt->rt6i_src.plen && saddr) {
@@ -1885,7 +1887,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 		 */
 		struct rt6_info *uncached_rt;
 
-		uncached_rt = ip6_rt_cache_alloc(res.f6i, &fl6->daddr, NULL);
+		uncached_rt = ip6_rt_cache_alloc(&res, &fl6->daddr, NULL);
 
 		rcu_read_unlock();
 
@@ -2329,15 +2331,16 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
 		if (rt6->rt6i_flags & RTF_CACHE)
 			rt6_update_exception_stamp_rt(rt6);
 	} else if (daddr) {
-		struct fib6_info *from;
+		struct fib6_result res = {};
 		struct rt6_info *nrt6;
 
 		rcu_read_lock();
-		from = rcu_dereference(rt6->from);
-		nrt6 = ip6_rt_cache_alloc(from, daddr, saddr);
+		res.f6i = rcu_dereference(rt6->from);
+		res.nh = &res.f6i->fib6_nh;
+		nrt6 = ip6_rt_cache_alloc(&res, daddr, saddr);
 		if (nrt6) {
 			rt6_do_update_pmtu(nrt6, mtu);
-			if (rt6_insert_exception(nrt6, from))
+			if (rt6_insert_exception(nrt6, res.f6i))
 				dst_release_immediate(&nrt6->dst);
 		}
 		rcu_read_unlock();
@@ -3360,10 +3363,10 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
 {
 	struct netevent_redirect netevent;
 	struct rt6_info *rt, *nrt = NULL;
+	struct fib6_result res = {};
 	struct ndisc_options ndopts;
 	struct inet6_dev *in6_dev;
 	struct neighbour *neigh;
-	struct fib6_info *from;
 	struct rd_msg *msg;
 	int optlen, on_link;
 	u8 *lladdr;
@@ -3446,14 +3449,15 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
 		     NDISC_REDIRECT, &ndopts);
 
 	rcu_read_lock();
-	from = rcu_dereference(rt->from);
+	res.f6i = rcu_dereference(rt->from);
 	/* This fib6_info_hold() is safe here because we hold reference to rt
 	 * and rt already holds reference to fib6_info.
 	 */
-	fib6_info_hold(from);
+	fib6_info_hold(res.f6i);
 	rcu_read_unlock();
 
-	nrt = ip6_rt_cache_alloc(from, &msg->dest, NULL);
+	res.nh = &res.f6i->fib6_nh;
+	nrt = ip6_rt_cache_alloc(&res, &msg->dest, NULL);
 	if (!nrt)
 		goto out;
 
@@ -3467,7 +3471,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
 	 * a cached route because rt6_insert_exception() will
 	 * takes care of it
 	 */
-	if (rt6_insert_exception(nrt, from)) {
+	if (rt6_insert_exception(nrt, res.f6i)) {
 		dst_release_immediate(&nrt->dst);
 		goto out;
 	}
@@ -3479,7 +3483,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
 	call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
 
 out:
-	fib6_info_release(from);
+	fib6_info_release(res.f6i);
 	neigh_release(neigh);
 }
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 04/13] ipv6: Pass fib6_result to ip6_create_rt_rcu
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
                   ` (2 preceding siblings ...)
  2019-04-16 21:36 ` [PATCH v2 net-next 03/13] ipv6: Pass fib6_result to ip6_rt_cache_alloc David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 05/13] ipv6: Pass fib6_result to pcpu route functions David Ahern
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Change ip6_create_rt_rcu to take fib6_result over a fib6_info.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/route.c | 37 +++++++++++++++++++++----------------
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index f267b3060ac7..5e84d0894f6b 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1038,22 +1038,24 @@ static bool ip6_hold_safe(struct net *net, struct rt6_info **prt)
 }
 
 /* called with rcu_lock held */
-static struct rt6_info *ip6_create_rt_rcu(struct fib6_info *rt)
+static struct rt6_info *ip6_create_rt_rcu(const struct fib6_result *res)
 {
-	unsigned short flags = fib6_info_dst_flags(rt);
-	struct net_device *dev = rt->fib6_nh.fib_nh_dev;
+	struct net_device *dev = res->nh->fib_nh_dev;
+	struct fib6_info *f6i = res->f6i;
+	unsigned short flags;
 	struct rt6_info *nrt;
 
-	if (!fib6_info_hold_safe(rt))
+	if (!fib6_info_hold_safe(f6i))
 		goto fallback;
 
+	flags = fib6_info_dst_flags(f6i);
 	nrt = ip6_dst_alloc(dev_net(dev), dev, flags);
 	if (!nrt) {
-		fib6_info_release(rt);
+		fib6_info_release(f6i);
 		goto fallback;
 	}
 
-	ip6_rt_copy_init(nrt, rt);
+	ip6_rt_copy_init(nrt, f6i);
 	return nrt;
 
 fallback:
@@ -1104,7 +1106,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 		if (ip6_hold_safe(net, &rt))
 			dst_use_noref(&rt->dst, jiffies);
 	} else {
-		rt = ip6_create_rt_rcu(res.f6i);
+		rt = ip6_create_rt_rcu(&res);
 	}
 
 out:
@@ -2413,12 +2415,13 @@ void ip6_sk_dst_store_flow(struct sock *sk, struct dst_entry *dst,
 		      NULL);
 }
 
-static bool ip6_redirect_nh_match(struct fib6_info *f6i,
-				  struct fib6_nh *nh,
+static bool ip6_redirect_nh_match(const struct fib6_result *res,
 				  struct flowi6 *fl6,
 				  const struct in6_addr *gw,
 				  struct rt6_info **ret)
 {
+	const struct fib6_nh *nh = res->nh;
+
 	if (nh->fib_nh_flags & RTNH_F_DEAD || !nh->fib_nh_gw_family ||
 	    fl6->flowi6_oif != nh->fib_nh_dev->ifindex)
 		return false;
@@ -2429,12 +2432,9 @@ static bool ip6_redirect_nh_match(struct fib6_info *f6i,
 	 * is different.
 	 */
 	if (!ipv6_addr_equal(gw, &nh->fib_nh_gw6)) {
-		struct fib6_result res = {
-			.f6i = f6i,
-		};
 		struct rt6_info *rt_cache;
 
-		rt_cache = rt6_find_cached_rt(&res, &fl6->daddr, &fl6->saddr);
+		rt_cache = rt6_find_cached_rt(res, &fl6->daddr, &fl6->saddr);
 		if (rt_cache &&
 		    ipv6_addr_equal(gw, &rt_cache->rt6i_gateway)) {
 			*ret = rt_cache;
@@ -2459,6 +2459,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
 {
 	struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
 	struct rt6_info *ret = NULL;
+	struct fib6_result res = {};
 	struct fib6_info *rt;
 	struct fib6_node *fn;
 
@@ -2476,12 +2477,14 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
 	fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
 restart:
 	for_each_fib6_node_rt_rcu(fn) {
+		res.f6i = rt;
+		res.nh = &rt->fib6_nh;
+
 		if (fib6_check_expired(rt))
 			continue;
 		if (rt->fib6_flags & RTF_REJECT)
 			break;
-		if (ip6_redirect_nh_match(rt, &rt->fib6_nh, fl6,
-					  &rdfl->gateway, &ret))
+		if (ip6_redirect_nh_match(&res, fl6, &rdfl->gateway, &ret))
 			goto out;
 	}
 
@@ -2498,11 +2501,13 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
 			goto restart;
 	}
 
+	res.f6i = rt;
+	res.nh = &rt->fib6_nh;
 out:
 	if (ret)
 		ip6_hold_safe(net, &ret);
 	else
-		ret = ip6_create_rt_rcu(rt);
+		ret = ip6_create_rt_rcu(&res);
 
 	rcu_read_unlock();
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 05/13] ipv6: Pass fib6_result to pcpu route functions
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
                   ` (3 preceding siblings ...)
  2019-04-16 21:36 ` [PATCH v2 net-next 04/13] ipv6: Pass fib6_result to ip6_create_rt_rcu David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 06/13] ipv6: Pass fib6_result to ip6_rt_get_dev_rcu and ip6_rt_copy_init David Ahern
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Update ip6_rt_pcpu_alloc, rt6_get_pcpu_route and rt6_make_pcpu_route
to a fib6_result over a fib6_info.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/route.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 5e84d0894f6b..ebd119a6de89 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1220,34 +1220,35 @@ static struct rt6_info *ip6_rt_cache_alloc(const struct fib6_result *res,
 	return rt;
 }
 
-static struct rt6_info *ip6_rt_pcpu_alloc(struct fib6_info *rt)
+static struct rt6_info *ip6_rt_pcpu_alloc(const struct fib6_result *res)
 {
-	unsigned short flags = fib6_info_dst_flags(rt);
+	struct fib6_info *f6i = res->f6i;
+	unsigned short flags = fib6_info_dst_flags(f6i);
 	struct net_device *dev;
 	struct rt6_info *pcpu_rt;
 
-	if (!fib6_info_hold_safe(rt))
+	if (!fib6_info_hold_safe(f6i))
 		return NULL;
 
 	rcu_read_lock();
-	dev = ip6_rt_get_dev_rcu(rt);
+	dev = ip6_rt_get_dev_rcu(f6i);
 	pcpu_rt = ip6_dst_alloc(dev_net(dev), dev, flags);
 	rcu_read_unlock();
 	if (!pcpu_rt) {
-		fib6_info_release(rt);
+		fib6_info_release(f6i);
 		return NULL;
 	}
-	ip6_rt_copy_init(pcpu_rt, rt);
+	ip6_rt_copy_init(pcpu_rt, f6i);
 	pcpu_rt->rt6i_flags |= RTF_PCPU;
 	return pcpu_rt;
 }
 
 /* It should be called with rcu_read_lock() acquired */
-static struct rt6_info *rt6_get_pcpu_route(struct fib6_info *rt)
+static struct rt6_info *rt6_get_pcpu_route(const struct fib6_result *res)
 {
 	struct rt6_info *pcpu_rt, **p;
 
-	p = this_cpu_ptr(rt->rt6i_pcpu);
+	p = this_cpu_ptr(res->f6i->rt6i_pcpu);
 	pcpu_rt = *p;
 
 	if (pcpu_rt)
@@ -1257,18 +1258,18 @@ static struct rt6_info *rt6_get_pcpu_route(struct fib6_info *rt)
 }
 
 static struct rt6_info *rt6_make_pcpu_route(struct net *net,
-					    struct fib6_info *rt)
+					    const struct fib6_result *res)
 {
 	struct rt6_info *pcpu_rt, *prev, **p;
 
-	pcpu_rt = ip6_rt_pcpu_alloc(rt);
+	pcpu_rt = ip6_rt_pcpu_alloc(res);
 	if (!pcpu_rt) {
 		dst_hold(&net->ipv6.ip6_null_entry->dst);
 		return net->ipv6.ip6_null_entry;
 	}
 
 	dst_hold(&pcpu_rt->dst);
-	p = this_cpu_ptr(rt->rt6i_pcpu);
+	p = this_cpu_ptr(res->f6i->rt6i_pcpu);
 	prev = cmpxchg(p, NULL, pcpu_rt);
 	BUG_ON(prev);
 
@@ -1911,10 +1912,10 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 		struct rt6_info *pcpu_rt;
 
 		local_bh_disable();
-		pcpu_rt = rt6_get_pcpu_route(res.f6i);
+		pcpu_rt = rt6_get_pcpu_route(&res);
 
 		if (!pcpu_rt)
-			pcpu_rt = rt6_make_pcpu_route(net, res.f6i);
+			pcpu_rt = rt6_make_pcpu_route(net, &res);
 
 		local_bh_enable();
 		rcu_read_unlock();
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 06/13] ipv6: Pass fib6_result to ip6_rt_get_dev_rcu and ip6_rt_copy_init
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
                   ` (4 preceding siblings ...)
  2019-04-16 21:36 ` [PATCH v2 net-next 05/13] ipv6: Pass fib6_result to pcpu route functions David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 07/13] ipv6: Pass fib6_result to rt6_insert_exception David Ahern
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Now that all callers are update to have a fib6_result, pass it down
to ip6_rt_get_dev_rcu, ip6_rt_copy_init, and ip6_rt_init_dst.

In the process, change ort to f6i in ip6_rt_copy_init to make it
clear it is a reference to a fib6_info.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/route.c | 49 +++++++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 22 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index ebd119a6de89..834437e3602b 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -871,17 +871,18 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
  */
 
 /* called with rcu_lock held */
-static struct net_device *ip6_rt_get_dev_rcu(struct fib6_info *rt)
+static struct net_device *ip6_rt_get_dev_rcu(const struct fib6_result *res)
 {
-	struct net_device *dev = rt->fib6_nh.fib_nh_dev;
+	struct net_device *dev = res->nh->fib_nh_dev;
+	const struct fib6_info *f6i = res->f6i;
 
-	if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) {
+	if (f6i->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) {
 		/* for copies of local routes, dst->dev needs to be the
 		 * device if it is a master device, the master device if
 		 * device is enslaved, and the loopback as the default
 		 */
 		if (netif_is_l3_slave(dev) &&
-		    !rt6_need_strict(&rt->fib6_dst.addr))
+		    !rt6_need_strict(&f6i->fib6_dst.addr))
 			dev = l3mdev_master_dev_rcu(dev);
 		else if (!netif_is_l3_master(dev))
 			dev = dev_net(dev)->loopback_dev;
@@ -949,8 +950,10 @@ static void ip6_rt_init_dst_reject(struct rt6_info *rt, struct fib6_info *ort)
 	}
 }
 
-static void ip6_rt_init_dst(struct rt6_info *rt, struct fib6_info *ort)
+static void ip6_rt_init_dst(struct rt6_info *rt, const struct fib6_result *res)
 {
+	struct fib6_info *ort = res->f6i;
+
 	if (ort->fib6_flags & RTF_REJECT) {
 		ip6_rt_init_dst_reject(rt, ort);
 		return;
@@ -967,8 +970,8 @@ static void ip6_rt_init_dst(struct rt6_info *rt, struct fib6_info *ort)
 		rt->dst.input = ip6_forward;
 	}
 
-	if (ort->fib6_nh.fib_nh_lws) {
-		rt->dst.lwtstate = lwtstate_get(ort->fib6_nh.fib_nh_lws);
+	if (res->nh->fib_nh_lws) {
+		rt->dst.lwtstate = lwtstate_get(res->nh->fib_nh_lws);
 		lwtunnel_set_redirect(&rt->dst);
 	}
 
@@ -983,23 +986,25 @@ static void rt6_set_from(struct rt6_info *rt, struct fib6_info *from)
 	ip_dst_init_metrics(&rt->dst, from->fib6_metrics);
 }
 
-/* Caller must already hold reference to @ort */
-static void ip6_rt_copy_init(struct rt6_info *rt, struct fib6_info *ort)
+/* Caller must already hold reference to f6i in result */
+static void ip6_rt_copy_init(struct rt6_info *rt, const struct fib6_result *res)
 {
-	struct net_device *dev = fib6_info_nh_dev(ort);
+	const struct fib6_nh *nh = res->nh;
+	const struct net_device *dev = nh->fib_nh_dev;
+	struct fib6_info *f6i = res->f6i;
 
-	ip6_rt_init_dst(rt, ort);
+	ip6_rt_init_dst(rt, res);
 
-	rt->rt6i_dst = ort->fib6_dst;
+	rt->rt6i_dst = f6i->fib6_dst;
 	rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL;
-	rt->rt6i_flags = ort->fib6_flags;
-	if (ort->fib6_nh.fib_nh_gw_family) {
-		rt->rt6i_gateway = ort->fib6_nh.fib_nh_gw6;
+	rt->rt6i_flags = f6i->fib6_flags;
+	if (nh->fib_nh_gw_family) {
+		rt->rt6i_gateway = nh->fib_nh_gw6;
 		rt->rt6i_flags |= RTF_GATEWAY;
 	}
-	rt6_set_from(rt, ort);
+	rt6_set_from(rt, f6i);
 #ifdef CONFIG_IPV6_SUBTREES
-	rt->rt6i_src = ort->fib6_src;
+	rt->rt6i_src = f6i->fib6_src;
 #endif
 }
 
@@ -1055,7 +1060,7 @@ static struct rt6_info *ip6_create_rt_rcu(const struct fib6_result *res)
 		goto fallback;
 	}
 
-	ip6_rt_copy_init(nrt, f6i);
+	ip6_rt_copy_init(nrt, res);
 	return nrt;
 
 fallback:
@@ -1192,14 +1197,14 @@ static struct rt6_info *ip6_rt_cache_alloc(const struct fib6_result *res,
 	if (!fib6_info_hold_safe(f6i))
 		return NULL;
 
-	dev = ip6_rt_get_dev_rcu(f6i);
+	dev = ip6_rt_get_dev_rcu(res);
 	rt = ip6_dst_alloc(dev_net(dev), dev, 0);
 	if (!rt) {
 		fib6_info_release(f6i);
 		return NULL;
 	}
 
-	ip6_rt_copy_init(rt, res->f6i);
+	ip6_rt_copy_init(rt, res);
 	rt->rt6i_flags |= RTF_CACHE;
 	rt->dst.flags |= DST_HOST;
 	rt->rt6i_dst.addr = *daddr;
@@ -1231,14 +1236,14 @@ static struct rt6_info *ip6_rt_pcpu_alloc(const struct fib6_result *res)
 		return NULL;
 
 	rcu_read_lock();
-	dev = ip6_rt_get_dev_rcu(f6i);
+	dev = ip6_rt_get_dev_rcu(res);
 	pcpu_rt = ip6_dst_alloc(dev_net(dev), dev, flags);
 	rcu_read_unlock();
 	if (!pcpu_rt) {
 		fib6_info_release(f6i);
 		return NULL;
 	}
-	ip6_rt_copy_init(pcpu_rt, f6i);
+	ip6_rt_copy_init(pcpu_rt, res);
 	pcpu_rt->rt6i_flags |= RTF_PCPU;
 	return pcpu_rt;
 }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 07/13] ipv6: Pass fib6_result to rt6_insert_exception
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
                   ` (5 preceding siblings ...)
  2019-04-16 21:36 ` [PATCH v2 net-next 06/13] ipv6: Pass fib6_result to ip6_rt_get_dev_rcu and ip6_rt_copy_init David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 08/13] ipv6: Pass fib6_result to ip6_mtu_from_fib6 and fib6_mtu David Ahern
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Update rt6_insert_exception to take a fib6_result over a fib6_info.
Change ort to f6i from the fib6_result and rename to better reflect
what it references (a fib6_info).

Since this function is already getting changed, update the comments
to reference fib6_info variables rather than the older rt6_info.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/route.c | 33 +++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 834437e3602b..7d88bb1401ed 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1439,22 +1439,23 @@ static unsigned int fib6_mtu(const struct fib6_info *rt)
 }
 
 static int rt6_insert_exception(struct rt6_info *nrt,
-				struct fib6_info *ort)
+				const struct fib6_result *res)
 {
 	struct net *net = dev_net(nrt->dst.dev);
 	struct rt6_exception_bucket *bucket;
 	struct in6_addr *src_key = NULL;
 	struct rt6_exception *rt6_ex;
+	struct fib6_info *f6i = res->f6i;
 	int err = 0;
 
 	spin_lock_bh(&rt6_exception_lock);
 
-	if (ort->exception_bucket_flushed) {
+	if (f6i->exception_bucket_flushed) {
 		err = -EINVAL;
 		goto out;
 	}
 
-	bucket = rcu_dereference_protected(ort->rt6i_exception_bucket,
+	bucket = rcu_dereference_protected(f6i->rt6i_exception_bucket,
 					lockdep_is_held(&rt6_exception_lock));
 	if (!bucket) {
 		bucket = kcalloc(FIB6_EXCEPTION_BUCKET_SIZE, sizeof(*bucket),
@@ -1463,24 +1464,24 @@ static int rt6_insert_exception(struct rt6_info *nrt,
 			err = -ENOMEM;
 			goto out;
 		}
-		rcu_assign_pointer(ort->rt6i_exception_bucket, bucket);
+		rcu_assign_pointer(f6i->rt6i_exception_bucket, bucket);
 	}
 
 #ifdef CONFIG_IPV6_SUBTREES
-	/* rt6i_src.plen != 0 indicates ort is in subtree
+	/* fib6_src.plen != 0 indicates f6i is in subtree
 	 * and exception table is indexed by a hash of
-	 * both rt6i_dst and rt6i_src.
+	 * both fib6_dst and fib6_src.
 	 * Otherwise, the exception table is indexed by
-	 * a hash of only rt6i_dst.
+	 * a hash of only fib6_dst.
 	 */
-	if (ort->fib6_src.plen)
+	if (f6i->fib6_src.plen)
 		src_key = &nrt->rt6i_src.addr;
 #endif
-	/* rt6_mtu_change() might lower mtu on ort.
+	/* rt6_mtu_change() might lower mtu on f6i.
 	 * Only insert this exception route if its mtu
-	 * is less than ort's mtu value.
+	 * is less than f6i's mtu value.
 	 */
-	if (dst_metric_raw(&nrt->dst, RTAX_MTU) >= fib6_mtu(ort)) {
+	if (dst_metric_raw(&nrt->dst, RTAX_MTU) >= fib6_mtu(res->f6i)) {
 		err = -EINVAL;
 		goto out;
 	}
@@ -1509,9 +1510,9 @@ static int rt6_insert_exception(struct rt6_info *nrt,
 
 	/* Update fn->fn_sernum to invalidate all cached dst */
 	if (!err) {
-		spin_lock_bh(&ort->fib6_table->tb6_lock);
-		fib6_update_sernum(net, ort);
-		spin_unlock_bh(&ort->fib6_table->tb6_lock);
+		spin_lock_bh(&f6i->fib6_table->tb6_lock);
+		fib6_update_sernum(net, f6i);
+		spin_unlock_bh(&f6i->fib6_table->tb6_lock);
 		fib6_force_start_gc(net);
 	}
 
@@ -2348,7 +2349,7 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
 		nrt6 = ip6_rt_cache_alloc(&res, daddr, saddr);
 		if (nrt6) {
 			rt6_do_update_pmtu(nrt6, mtu);
-			if (rt6_insert_exception(nrt6, res.f6i))
+			if (rt6_insert_exception(nrt6, &res))
 				dst_release_immediate(&nrt6->dst);
 		}
 		rcu_read_unlock();
@@ -3482,7 +3483,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
 	 * a cached route because rt6_insert_exception() will
 	 * takes care of it
 	 */
-	if (rt6_insert_exception(nrt, res.f6i)) {
+	if (rt6_insert_exception(nrt, &res)) {
 		dst_release_immediate(&nrt->dst);
 		goto out;
 	}
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 08/13] ipv6: Pass fib6_result to ip6_mtu_from_fib6 and fib6_mtu
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
                   ` (6 preceding siblings ...)
  2019-04-16 21:36 ` [PATCH v2 net-next 07/13] ipv6: Pass fib6_result to rt6_insert_exception David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 09/13] ipv6: Pass fib6_result to rt6_device_match David Ahern
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Change ip6_mtu_from_fib6 and fib6_mtu to take a fib6_result over a
fib6_info. Update both to use the fib6_nh from fib6_result.

Since the signature of ip6_mtu_from_fib6 is already changing, add const
to daddr and saddr.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/ip6_route.h  |  5 +++--
 include/net/ipv6_stubs.h |  5 +++--
 net/core/filter.c        |  2 +-
 net/ipv6/addrconf_core.c |  5 +++--
 net/ipv6/route.c         | 26 +++++++++++++++-----------
 5 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 5909fc421305..46bbd8ff9cc6 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -302,8 +302,9 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
 	return mtu;
 }
 
-u32 ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr,
-		      struct in6_addr *saddr);
+u32 ip6_mtu_from_fib6(const struct fib6_result *res,
+		      const struct in6_addr *daddr,
+		      const struct in6_addr *saddr);
 
 struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw,
 				   struct net_device *dev, struct sk_buff *skb,
diff --git a/include/net/ipv6_stubs.h b/include/net/ipv6_stubs.h
index 5df36d6a2613..0d16b9ec0485 100644
--- a/include/net/ipv6_stubs.h
+++ b/include/net/ipv6_stubs.h
@@ -38,8 +38,9 @@ struct ipv6_stub {
 	void (*fib6_select_path)(const struct net *net, struct fib6_result *res,
 				 struct flowi6 *fl6, int oif, bool oif_match,
 				 const struct sk_buff *skb, int strict);
-	u32 (*ip6_mtu_from_fib6)(struct fib6_info *f6i, struct in6_addr *daddr,
-				 struct in6_addr *saddr);
+	u32 (*ip6_mtu_from_fib6)(const struct fib6_result *res,
+				 const struct in6_addr *daddr,
+				 const struct in6_addr *saddr);
 
 	int (*fib6_nh_init)(struct net *net, struct fib6_nh *fib6_nh,
 			    struct fib6_config *cfg, gfp_t gfp_flags,
diff --git a/net/core/filter.c b/net/core/filter.c
index 72b29e4d705b..3dd22f450271 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4759,7 +4759,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
 				    fl6.flowi6_oif != 0, NULL, strict);
 
 	if (check_mtu) {
-		mtu = ipv6_stub->ip6_mtu_from_fib6(res.f6i, dst, src);
+		mtu = ipv6_stub->ip6_mtu_from_fib6(&res, dst, src);
 		if (params->tot_len > mtu)
 			return BPF_FIB_LKUP_RET_FRAG_NEEDED;
 	}
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index b11fa0aa18a0..c4c0203d6836 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -166,8 +166,9 @@ eafnosupport_fib6_select_path(const struct net *net, struct fib6_result *res,
 }
 
 static u32
-eafnosupport_ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr,
-			       struct in6_addr *saddr)
+eafnosupport_ip6_mtu_from_fib6(const struct fib6_result *res,
+			       const struct in6_addr *daddr,
+			       const struct in6_addr *saddr)
 {
 	return 0;
 }
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 7d88bb1401ed..c28fd554f7cf 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1417,14 +1417,15 @@ __rt6_find_exception_rcu(struct rt6_exception_bucket **bucket,
 	return NULL;
 }
 
-static unsigned int fib6_mtu(const struct fib6_info *rt)
+static unsigned int fib6_mtu(const struct fib6_result *res)
 {
+	const struct fib6_nh *nh = res->nh;
 	unsigned int mtu;
 
-	if (rt->fib6_pmtu) {
-		mtu = rt->fib6_pmtu;
+	if (res->f6i->fib6_pmtu) {
+		mtu = res->f6i->fib6_pmtu;
 	} else {
-		struct net_device *dev = fib6_info_nh_dev(rt);
+		struct net_device *dev = nh->fib_nh_dev;
 		struct inet6_dev *idev;
 
 		rcu_read_lock();
@@ -1435,7 +1436,7 @@ static unsigned int fib6_mtu(const struct fib6_info *rt)
 
 	mtu = min_t(unsigned int, mtu, IP6_MAX_MTU);
 
-	return mtu - lwtunnel_headroom(rt->fib6_nh.fib_nh_lws, mtu);
+	return mtu - lwtunnel_headroom(nh->fib_nh_lws, mtu);
 }
 
 static int rt6_insert_exception(struct rt6_info *nrt,
@@ -1481,7 +1482,7 @@ static int rt6_insert_exception(struct rt6_info *nrt,
 	 * Only insert this exception route if its mtu
 	 * is less than f6i's mtu value.
 	 */
-	if (dst_metric_raw(&nrt->dst, RTAX_MTU) >= fib6_mtu(res->f6i)) {
+	if (dst_metric_raw(&nrt->dst, RTAX_MTU) >= fib6_mtu(res)) {
 		err = -EINVAL;
 		goto out;
 	}
@@ -2636,12 +2637,15 @@ static unsigned int ip6_mtu(const struct dst_entry *dst)
  * based on ip6_dst_mtu_forward and exception logic of
  * rt6_find_cached_rt; called with rcu_read_lock
  */
-u32 ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr,
-		      struct in6_addr *saddr)
+u32 ip6_mtu_from_fib6(const struct fib6_result *res,
+		      const struct in6_addr *daddr,
+		      const struct in6_addr *saddr)
 {
 	struct rt6_exception_bucket *bucket;
+	const struct fib6_nh *nh = res->nh;
+	struct fib6_info *f6i = res->f6i;
+	const struct in6_addr *src_key;
 	struct rt6_exception *rt6_ex;
-	struct in6_addr *src_key;
 	struct inet6_dev *idev;
 	u32 mtu = 0;
 
@@ -2663,7 +2667,7 @@ u32 ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr,
 		mtu = dst_metric_raw(&rt6_ex->rt6i->dst, RTAX_MTU);
 
 	if (likely(!mtu)) {
-		struct net_device *dev = fib6_info_nh_dev(f6i);
+		struct net_device *dev = nh->fib_nh_dev;
 
 		mtu = IPV6_MIN_MTU;
 		idev = __in6_dev_get(dev);
@@ -2673,7 +2677,7 @@ u32 ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr,
 
 	mtu = min_t(unsigned int, mtu, IP6_MAX_MTU);
 out:
-	return mtu - lwtunnel_headroom(fib6_info_nh_lwt(f6i), mtu);
+	return mtu - lwtunnel_headroom(nh->fib_nh_lws, mtu);
 }
 
 struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 09/13] ipv6: Pass fib6_result to rt6_device_match
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
                   ` (7 preceding siblings ...)
  2019-04-16 21:36 ` [PATCH v2 net-next 08/13] ipv6: Pass fib6_result to ip6_mtu_from_fib6 and fib6_mtu David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 10/13] ipv6: Pass fib6_result to rt6_select and find_rr_leaf David Ahern
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Pass fib6_result to rt6_device_match with f6i set. rt6_device_match
updates f6i in the result if it finds a better match and sets nh.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/route.c | 49 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 30 insertions(+), 19 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c28fd554f7cf..7a3eecdb933d 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -491,29 +491,40 @@ static bool __rt6_device_match(struct net *net, const struct fib6_nh *nh,
 	return false;
 }
 
-static inline struct fib6_info *rt6_device_match(struct net *net,
-						 struct fib6_info *rt,
-						    const struct in6_addr *saddr,
-						    int oif,
-						    int flags)
+static void rt6_device_match(struct net *net, struct fib6_result *res,
+			     const struct in6_addr *saddr, int oif, int flags)
 {
-	const struct fib6_nh *nh;
-	struct fib6_info *sprt;
+	struct fib6_info *f6i = res->f6i;
+	struct fib6_info *spf6i;
+	struct fib6_nh *nh;
 
-	if (!oif && ipv6_addr_any(saddr) &&
-	    !(rt->fib6_nh.fib_nh_flags & RTNH_F_DEAD))
-		return rt;
+	if (!oif && ipv6_addr_any(saddr)) {
+		nh = &f6i->fib6_nh;
+		if (!(nh->fib_nh_flags & RTNH_F_DEAD)) {
+			res->nh = nh;
+			return;
+		}
+	}
 
-	for (sprt = rt; sprt; sprt = rcu_dereference(sprt->fib6_next)) {
-		nh = &sprt->fib6_nh;
-		if (__rt6_device_match(net, nh, saddr, oif, flags))
-			return sprt;
+	for (spf6i = f6i; spf6i; spf6i = rcu_dereference(spf6i->fib6_next)) {
+		nh = &spf6i->fib6_nh;
+		if (__rt6_device_match(net, nh, saddr, oif, flags)) {
+			res->f6i = spf6i;
+			res->nh = nh;
+		}
 	}
 
-	if (oif && flags & RT6_LOOKUP_F_IFACE)
-		return net->ipv6.fib6_null_entry;
+	if (oif && flags & RT6_LOOKUP_F_IFACE) {
+		res->f6i = net->ipv6.fib6_null_entry;
+		res->nh = &res->f6i->fib6_nh;
+		return;
+	}
 
-	return rt->fib6_nh.fib_nh_flags & RTNH_F_DEAD ? net->ipv6.fib6_null_entry : rt;
+	res->nh = &f6i->fib6_nh;
+	if (res->nh->fib_nh_flags & RTNH_F_DEAD) {
+		res->f6i = net->ipv6.fib6_null_entry;
+		res->nh = &res->f6i->fib6_nh;
+	}
 }
 
 #ifdef CONFIG_IPV6_ROUTER_PREF
@@ -1089,8 +1100,8 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 	if (!res.f6i)
 		res.f6i = net->ipv6.fib6_null_entry;
 	else
-		res.f6i = rt6_device_match(net, res.f6i, &fl6->saddr,
-					   fl6->flowi6_oif, flags);
+		rt6_device_match(net, &res, &fl6->saddr, fl6->flowi6_oif,
+				 flags);
 
 	if (res.f6i == net->ipv6.fib6_null_entry) {
 		fn = fib6_backtrack(fn, &fl6->saddr);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 10/13] ipv6: Pass fib6_result to rt6_select and find_rr_leaf
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
                   ` (8 preceding siblings ...)
  2019-04-16 21:36 ` [PATCH v2 net-next 09/13] ipv6: Pass fib6_result to rt6_device_match David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 11/13] ipv6: Pass fib6_result to fib6_table_lookup tracepoint David Ahern
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Pass fib6_result to rt6_select. Instead of returning the fib entry, it
will set f6i and nh based on the lookup.

find_rr_leaf is changed to remove the match option in favor of taking
fib6_result and having __find_rr_leaf set f6i in the result.

In the process, update fib6_info references in __find_rr_leaf to f6i names.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/route.c | 82 +++++++++++++++++++++++++++++---------------------------
 1 file changed, 43 insertions(+), 39 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 7a3eecdb933d..de2a901b4d30 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -695,66 +695,68 @@ static bool find_match(struct fib6_nh *nh, u32 fib6_flags,
 	return rc;
 }
 
-static void __find_rr_leaf(struct fib6_info *rt_start,
+static void __find_rr_leaf(struct fib6_info *f6i_start,
 			   struct fib6_info *nomatch, u32 metric,
-			   struct fib6_info **match, struct fib6_info **cont,
+			   struct fib6_result *res, struct fib6_info **cont,
 			   int oif, int strict, bool *do_rr, int *mpri)
 {
-	struct fib6_info *rt;
+	struct fib6_info *f6i;
 
-	for (rt = rt_start;
-	     rt && rt != nomatch;
-	     rt = rcu_dereference(rt->fib6_next)) {
+	for (f6i = f6i_start;
+	     f6i && f6i != nomatch;
+	     f6i = rcu_dereference(f6i->fib6_next)) {
 		struct fib6_nh *nh;
 
-		if (cont && rt->fib6_metric != metric) {
-			*cont = rt;
+		if (cont && f6i->fib6_metric != metric) {
+			*cont = f6i;
 			return;
 		}
 
-		if (fib6_check_expired(rt))
+		if (fib6_check_expired(f6i))
 			continue;
 
-		nh = &rt->fib6_nh;
-		if (find_match(nh, rt->fib6_flags, oif, strict, mpri, do_rr))
-			*match = rt;
+		nh = &f6i->fib6_nh;
+		if (find_match(nh, f6i->fib6_flags, oif, strict, mpri, do_rr)) {
+			res->f6i = f6i;
+			res->nh = nh;
+		}
 	}
 }
 
-static struct fib6_info *find_rr_leaf(struct fib6_node *fn,
-				      struct fib6_info *leaf,
-				      struct fib6_info *rr_head,
-				      u32 metric, int oif, int strict,
-				      bool *do_rr)
+static void find_rr_leaf(struct fib6_node *fn, struct fib6_info *leaf,
+			 struct fib6_info *rr_head, int oif, int strict,
+			 bool *do_rr, struct fib6_result *res)
 {
-	struct fib6_info *match = NULL, *cont = NULL;
+	u32 metric = rr_head->fib6_metric;
+	struct fib6_info *cont = NULL;
 	int mpri = -1;
 
-	__find_rr_leaf(rr_head, NULL, metric, &match, &cont,
+	__find_rr_leaf(rr_head, NULL, metric, res, &cont,
 		       oif, strict, do_rr, &mpri);
 
-	__find_rr_leaf(leaf, rr_head, metric, &match, &cont,
+	__find_rr_leaf(leaf, rr_head, metric, res, &cont,
 		       oif, strict, do_rr, &mpri);
 
-	if (match || !cont)
-		return match;
+	if (res->f6i || !cont)
+		return;
 
-	__find_rr_leaf(cont, NULL, metric, &match, NULL,
+	__find_rr_leaf(cont, NULL, metric, res, NULL,
 		       oif, strict, do_rr, &mpri);
-
-	return match;
 }
 
-static struct fib6_info *rt6_select(struct net *net, struct fib6_node *fn,
-				   int oif, int strict)
+static void rt6_select(struct net *net, struct fib6_node *fn, int oif,
+		       struct fib6_result *res, int strict)
 {
 	struct fib6_info *leaf = rcu_dereference(fn->leaf);
-	struct fib6_info *match, *rt0;
+	struct fib6_info *rt0;
 	bool do_rr = false;
 	int key_plen;
 
+	/* make sure this function or its helpers sets f6i */
+	res->f6i = NULL;
+
 	if (!leaf || leaf == net->ipv6.fib6_null_entry)
-		return net->ipv6.fib6_null_entry;
+		goto out;
 
 	rt0 = rcu_dereference(fn->rr_ptr);
 	if (!rt0)
@@ -771,11 +773,9 @@ static struct fib6_info *rt6_select(struct net *net, struct fib6_node *fn,
 		key_plen = rt0->fib6_src.plen;
 #endif
 	if (fn->fn_bit != key_plen)
-		return net->ipv6.fib6_null_entry;
-
-	match = find_rr_leaf(fn, leaf, rt0, rt0->fib6_metric, oif, strict,
-			     &do_rr);
+		goto out;
 
+	find_rr_leaf(fn, leaf, rt0, oif, strict, &do_rr, res);
 	if (do_rr) {
 		struct fib6_info *next = rcu_dereference(rt0->fib6_next);
 
@@ -792,7 +792,11 @@ static struct fib6_info *rt6_select(struct net *net, struct fib6_node *fn,
 		}
 	}
 
-	return match ? match : net->ipv6.fib6_null_entry;
+out:
+	if (!res->f6i) {
+		res->f6i = net->ipv6.fib6_null_entry;
+		res->nh = &res->f6i->fib6_nh;
+	}
 }
 
 static bool rt6_is_gw_or_nonexthop(const struct fib6_result *res)
@@ -1839,7 +1843,7 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
 				    int oif, struct flowi6 *fl6, int strict)
 {
 	struct fib6_node *fn, *saved_fn;
-	struct fib6_info *f6i;
+	struct fib6_result res;
 
 	fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
 	saved_fn = fn;
@@ -1848,8 +1852,8 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
 		oif = 0;
 
 redo_rt6_select:
-	f6i = rt6_select(net, fn, oif, strict);
-	if (f6i == net->ipv6.fib6_null_entry) {
+	rt6_select(net, fn, oif, &res, strict);
+	if (res.f6i == net->ipv6.fib6_null_entry) {
 		fn = fib6_backtrack(fn, &fl6->saddr);
 		if (fn)
 			goto redo_rt6_select;
@@ -1861,9 +1865,9 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
 		}
 	}
 
-	trace_fib6_table_lookup(net, f6i, table, fl6);
+	trace_fib6_table_lookup(net, res.f6i, table, fl6);
 
-	return f6i;
+	return res.f6i;
 }
 
 struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 11/13] ipv6: Pass fib6_result to fib6_table_lookup tracepoint
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
                   ` (9 preceding siblings ...)
  2019-04-16 21:36 ` [PATCH v2 net-next 10/13] ipv6: Pass fib6_result to rt6_select and find_rr_leaf David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 12/13] ipv6: Pass fib6_result to fib lookups David Ahern
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Change fib6_table_lookup tracepoint to take the fib6_result and use
the fib6_info and fib6_nh from it.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/trace/events/fib6.h | 16 ++++++++--------
 net/ipv6/route.c            |  6 +++---
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/include/trace/events/fib6.h b/include/trace/events/fib6.h
index 6d05ebdd669c..70e252d926ea 100644
--- a/include/trace/events/fib6.h
+++ b/include/trace/events/fib6.h
@@ -12,10 +12,10 @@
 
 TRACE_EVENT(fib6_table_lookup,
 
-	TP_PROTO(const struct net *net, const struct fib6_info *f6i,
+	TP_PROTO(const struct net *net, const struct fib6_result *res,
 		 struct fib6_table *table, const struct flowi6 *flp),
 
-	TP_ARGS(net, f6i, table, flp),
+	TP_ARGS(net, res, table, flp),
 
 	TP_STRUCT__entry(
 		__field(	u32,	tb_id		)
@@ -39,7 +39,7 @@ TRACE_EVENT(fib6_table_lookup,
 		struct in6_addr *in6;
 
 		__entry->tb_id = table->tb6_id;
-		__entry->err = ip6_rt_type_to_error(f6i->fib6_type);
+		__entry->err = ip6_rt_type_to_error(res->f6i->fib6_type);
 		__entry->oif = flp->flowi6_oif;
 		__entry->iif = flp->flowi6_iif;
 		__entry->tos = ip6_tclass(flp->flowlabel);
@@ -62,20 +62,20 @@ TRACE_EVENT(fib6_table_lookup,
 			__entry->dport = 0;
 		}
 
-		if (f6i->fib6_nh.fib_nh_dev) {
-			__assign_str(name, f6i->fib6_nh.fib_nh_dev);
+		if (res->nh && res->nh->fib_nh_dev) {
+			__assign_str(name, res->nh->fib_nh_dev);
 		} else {
 			__assign_str(name, "-");
 		}
-		if (f6i == net->ipv6.fib6_null_entry) {
+		if (res->f6i == net->ipv6.fib6_null_entry) {
 			struct in6_addr in6_zero = {};
 
 			in6 = (struct in6_addr *)__entry->gw;
 			*in6 = in6_zero;
 
-		} else if (f6i) {
+		} else if (res->nh) {
 			in6 = (struct in6_addr *)__entry->gw;
-			*in6 = f6i->fib6_nh.fib_nh_gw6;
+			*in6 = res->nh->fib_nh_gw6;
 		}
 	),
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index de2a901b4d30..e16d27df5dac 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1130,7 +1130,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 	}
 
 out:
-	trace_fib6_table_lookup(net, res.f6i, table, fl6);
+	trace_fib6_table_lookup(net, &res, table, fl6);
 
 	rcu_read_unlock();
 
@@ -1865,7 +1865,7 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
 		}
 	}
 
-	trace_fib6_table_lookup(net, res.f6i, table, fl6);
+	trace_fib6_table_lookup(net, &res, table, fl6);
 
 	return res.f6i;
 }
@@ -2534,7 +2534,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
 
 	rcu_read_unlock();
 
-	trace_fib6_table_lookup(net, rt, table, fl6);
+	trace_fib6_table_lookup(net, &res, table, fl6);
 	return ret;
 };
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 12/13] ipv6: Pass fib6_result to fib lookups
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
                   ` (10 preceding siblings ...)
  2019-04-16 21:36 ` [PATCH v2 net-next 11/13] ipv6: Pass fib6_result to fib6_table_lookup tracepoint David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-16 21:36 ` [PATCH v2 net-next 13/13] ipv6: Add fib6_type and fib6_flags to fib6_result David Ahern
  2019-04-18  6:16 ` [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Miller
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Change fib6_lookup and fib6_table_lookup to take a fib6_result and set
f6i and nh rather than returning a fib6_info. For now both always
return 0.

A later patch set can make these more like the IPv4 counterparts and
return EINVAL, EACCESS, etc based on fib6_type.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/ip6_fib.h    |  9 +++++----
 include/net/ipv6_stubs.h | 11 +++++------
 net/core/filter.c        | 10 +++++-----
 net/ipv6/addrconf_core.c | 13 +++++++------
 net/ipv6/fib6_rules.c    | 34 +++++++++++++---------------------
 net/ipv6/ip6_fib.c       |  7 ++++---
 net/ipv6/route.c         | 15 +++++++--------
 7 files changed, 46 insertions(+), 53 deletions(-)

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index c4d818041663..cb3277cd1413 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -389,12 +389,13 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
 /* called with rcu lock held; can return error pointer
  * caller needs to select path
  */
-struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
-			      int flags);
+int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
+		struct fib6_result *res, int flags);
 
 /* called with rcu lock held; caller needs to select path */
-struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
-				    int oif, struct flowi6 *fl6, int strict);
+int fib6_table_lookup(struct net *net, struct fib6_table *table,
+		      int oif, struct flowi6 *fl6, struct fib6_result *res,
+		      int strict);
 
 void fib6_select_path(const struct net *net, struct fib6_result *res,
 		      struct flowi6 *fl6, int oif, bool have_oif_match,
diff --git a/include/net/ipv6_stubs.h b/include/net/ipv6_stubs.h
index 0d16b9ec0485..6c0c4fde16f8 100644
--- a/include/net/ipv6_stubs.h
+++ b/include/net/ipv6_stubs.h
@@ -29,12 +29,11 @@ struct ipv6_stub {
 	int (*ipv6_route_input)(struct sk_buff *skb);
 
 	struct fib6_table *(*fib6_get_table)(struct net *net, u32 id);
-	struct fib6_info *(*fib6_lookup)(struct net *net, int oif,
-					 struct flowi6 *fl6, int flags);
-	struct fib6_info *(*fib6_table_lookup)(struct net *net,
-					      struct fib6_table *table,
-					      int oif, struct flowi6 *fl6,
-					      int flags);
+	int (*fib6_lookup)(struct net *net, int oif, struct flowi6 *fl6,
+			   struct fib6_result *res, int flags);
+	int (*fib6_table_lookup)(struct net *net, struct fib6_table *table,
+				 int oif, struct flowi6 *fl6,
+				 struct fib6_result *res, int flags);
 	void (*fib6_select_path)(const struct net *net, struct fib6_result *res,
 				 struct flowi6 *fl6, int oif, bool oif_match,
 				 const struct sk_buff *skb, int strict);
diff --git a/net/core/filter.c b/net/core/filter.c
index 3dd22f450271..599722d769e9 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4682,7 +4682,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
 	struct inet6_dev *idev;
 	struct flowi6 fl6;
 	int strict = 0;
-	int oif;
+	int oif, err;
 	u32 mtu;
 
 	/* link local addresses are never forwarded */
@@ -4724,18 +4724,18 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
 		if (unlikely(!tb))
 			return BPF_FIB_LKUP_RET_NOT_FWDED;
 
-		res.f6i = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6,
-						       strict);
+		err = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6, &res,
+						   strict);
 	} else {
 		fl6.flowi6_mark = 0;
 		fl6.flowi6_secid = 0;
 		fl6.flowi6_tun_key.tun_id = 0;
 		fl6.flowi6_uid = sock_net_uid(net, NULL);
 
-		res.f6i = ipv6_stub->fib6_lookup(net, oif, &fl6, strict);
+		err = ipv6_stub->fib6_lookup(net, oif, &fl6, &res, strict);
 	}
 
-	if (unlikely(IS_ERR_OR_NULL(res.f6i) ||
+	if (unlikely(err || IS_ERR_OR_NULL(res.f6i) ||
 		     res.f6i == net->ipv6.fib6_null_entry))
 		return BPF_FIB_LKUP_RET_NOT_FWDED;
 
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index c4c0203d6836..763a947e0d14 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -144,18 +144,19 @@ static struct fib6_table *eafnosupport_fib6_get_table(struct net *net, u32 id)
 	return NULL;
 }
 
-static struct fib6_info *
+static int
 eafnosupport_fib6_table_lookup(struct net *net, struct fib6_table *table,
-			       int oif, struct flowi6 *fl6, int flags)
+			       int oif, struct flowi6 *fl6,
+			       struct fib6_result *res, int flags)
 {
-	return NULL;
+	return -EAFNOSUPPORT;
 }
 
-static struct fib6_info *
+static int
 eafnosupport_fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
-			 int flags)
+			 struct fib6_result *res, int flags)
 {
-	return NULL;
+	return -EAFNOSUPPORT;
 }
 
 static void
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index f590446595d8..ab5ac643bae8 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -61,16 +61,16 @@ unsigned int fib6_rules_seq_read(struct net *net)
 }
 
 /* called with rcu lock held; no reference taken on fib6_info */
-struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
-			      int flags)
+int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
+		struct fib6_result *res, int flags)
 {
-	struct fib6_info *f6i;
 	int err;
 
 	if (net->ipv6.fib6_has_custom_rules) {
 		struct fib_lookup_arg arg = {
 			.lookup_ptr = fib6_table_lookup,
 			.lookup_data = &oif,
+			.result = res,
 			.flags = FIB_LOOKUP_NOREF,
 		};
 
@@ -78,19 +78,15 @@ struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
 
 		err = fib_rules_lookup(net->ipv6.fib6_rules_ops,
 				       flowi6_to_flowi(fl6), flags, &arg);
-		if (err)
-			return ERR_PTR(err);
-
-		f6i = arg.result ? : net->ipv6.fib6_null_entry;
 	} else {
-		f6i = fib6_table_lookup(net, net->ipv6.fib6_local_tbl,
-					oif, fl6, flags);
-		if (!f6i || f6i == net->ipv6.fib6_null_entry)
-			f6i = fib6_table_lookup(net, net->ipv6.fib6_main_tbl,
-						oif, fl6, flags);
+		err = fib6_table_lookup(net, net->ipv6.fib6_local_tbl, oif,
+					fl6, res, flags);
+		if (err || res->f6i == net->ipv6.fib6_null_entry)
+			err = fib6_table_lookup(net, net->ipv6.fib6_main_tbl,
+						oif, fl6, res, flags);
 	}
 
-	return f6i;
+	return err;
 }
 
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
@@ -157,10 +153,10 @@ static int fib6_rule_saddr(struct net *net, struct fib_rule *rule, int flags,
 static int fib6_rule_action_alt(struct fib_rule *rule, struct flowi *flp,
 				int flags, struct fib_lookup_arg *arg)
 {
+	struct fib6_result *res = arg->result;
 	struct flowi6 *flp6 = &flp->u.ip6;
 	struct net *net = rule->fr_net;
 	struct fib6_table *table;
-	struct fib6_info *f6i;
 	int err = -EAGAIN, *oif;
 	u32 tb_id;
 
@@ -182,14 +178,10 @@ static int fib6_rule_action_alt(struct fib_rule *rule, struct flowi *flp,
 		return -EAGAIN;
 
 	oif = (int *)arg->lookup_data;
-	f6i = fib6_table_lookup(net, table, *oif, flp6, flags);
-	if (f6i != net->ipv6.fib6_null_entry) {
+	err = fib6_table_lookup(net, table, *oif, flp6, res, flags);
+	if (!err && res->f6i != net->ipv6.fib6_null_entry)
 		err = fib6_rule_saddr(net, rule, flags, flp6,
-				      fib6_info_nh_dev(f6i));
-
-		if (likely(!err))
-			arg->result = f6i;
-	}
+				      res->nh->fib_nh_dev);
 
 	return err;
 }
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 46f54a5bb1f0..b47e15df9769 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -354,10 +354,11 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
 }
 
 /* called with rcu lock held; no reference taken on fib6_info */
-struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
-			      int flags)
+int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
+		struct fib6_result *res, int flags)
 {
-	return fib6_table_lookup(net, net->ipv6.fib6_main_tbl, oif, fl6, flags);
+	return fib6_table_lookup(net, net->ipv6.fib6_main_tbl, oif, fl6,
+				 res, flags);
 }
 
 static void __net_init fib6_tables_init(struct net *net)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index e16d27df5dac..f500f587de23 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1839,11 +1839,10 @@ void rt6_age_exceptions(struct fib6_info *rt,
 }
 
 /* must be called with rcu lock held */
-struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
-				    int oif, struct flowi6 *fl6, int strict)
+int fib6_table_lookup(struct net *net, struct fib6_table *table, int oif,
+		      struct flowi6 *fl6, struct fib6_result *res, int strict)
 {
 	struct fib6_node *fn, *saved_fn;
-	struct fib6_result res;
 
 	fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
 	saved_fn = fn;
@@ -1852,8 +1851,8 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
 		oif = 0;
 
 redo_rt6_select:
-	rt6_select(net, fn, oif, &res, strict);
-	if (res.f6i == net->ipv6.fib6_null_entry) {
+	rt6_select(net, fn, oif, res, strict);
+	if (res->f6i == net->ipv6.fib6_null_entry) {
 		fn = fib6_backtrack(fn, &fl6->saddr);
 		if (fn)
 			goto redo_rt6_select;
@@ -1865,9 +1864,9 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
 		}
 	}
 
-	trace_fib6_table_lookup(net, &res, table, fl6);
+	trace_fib6_table_lookup(net, res, table, fl6);
 
-	return res.f6i;
+	return 0;
 }
 
 struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
@@ -1885,7 +1884,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 
 	rcu_read_lock();
 
-	res.f6i = fib6_table_lookup(net, table, oif, fl6, strict);
+	fib6_table_lookup(net, table, oif, fl6, &res, strict);
 	if (res.f6i == net->ipv6.fib6_null_entry) {
 		rt = net->ipv6.ip6_null_entry;
 		rcu_read_unlock();
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 net-next 13/13] ipv6: Add fib6_type and fib6_flags to fib6_result
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
                   ` (11 preceding siblings ...)
  2019-04-16 21:36 ` [PATCH v2 net-next 12/13] ipv6: Pass fib6_result to fib lookups David Ahern
@ 2019-04-16 21:36 ` David Ahern
  2019-04-18  6:16 ` [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Miller
  13 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 21:36 UTC (permalink / raw)
  To: davem, netdev; +Cc: idosch, David Ahern

From: David Ahern <dsahern@gmail.com>

Add the fib6_flags and fib6_type to fib6_result. Update the lookup helpers
to set them and update post fib lookup users to use the version from the
result.

This allows nexthop objects to have blackhole nexthop.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/ip6_fib.h       |  2 ++
 include/trace/events/fib6.h |  2 +-
 net/core/filter.c           | 26 +++++++++----------
 net/ipv6/route.c            | 61 +++++++++++++++++++++++++++------------------
 4 files changed, 52 insertions(+), 39 deletions(-)

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index cb3277cd1413..6b7557b71c8c 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -193,6 +193,8 @@ struct rt6_info {
 struct fib6_result {
 	struct fib6_nh		*nh;
 	struct fib6_info	*f6i;
+	u32			fib6_flags;
+	u8			fib6_type;
 };
 
 #define for_each_fib6_node_rt_rcu(fn)					\
diff --git a/include/trace/events/fib6.h b/include/trace/events/fib6.h
index 70e252d926ea..c6abdcc77c12 100644
--- a/include/trace/events/fib6.h
+++ b/include/trace/events/fib6.h
@@ -39,7 +39,7 @@ TRACE_EVENT(fib6_table_lookup,
 		struct in6_addr *in6;
 
 		__entry->tb_id = table->tb6_id;
-		__entry->err = ip6_rt_type_to_error(res->f6i->fib6_type);
+		__entry->err = ip6_rt_type_to_error(res->fib6_type);
 		__entry->oif = flp->flowi6_oif;
 		__entry->iif = flp->flowi6_iif;
 		__entry->tos = ip6_tclass(flp->flowlabel);
diff --git a/net/core/filter.c b/net/core/filter.c
index 599722d769e9..91f8c9e1ecaa 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4739,21 +4739,19 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
 		     res.f6i == net->ipv6.fib6_null_entry))
 		return BPF_FIB_LKUP_RET_NOT_FWDED;
 
-	if (unlikely(res.f6i->fib6_flags & RTF_REJECT)) {
-		switch (res.f6i->fib6_type) {
-		case RTN_BLACKHOLE:
-			return BPF_FIB_LKUP_RET_BLACKHOLE;
-		case RTN_UNREACHABLE:
-			return BPF_FIB_LKUP_RET_UNREACHABLE;
-		case RTN_PROHIBIT:
-			return BPF_FIB_LKUP_RET_PROHIBIT;
-		default:
-			return BPF_FIB_LKUP_RET_NOT_FWDED;
-		}
-	}
-
-	if (res.f6i->fib6_type != RTN_UNICAST)
+	switch (res.fib6_type) {
+	/* only unicast is forwarded */
+	case RTN_UNICAST:
+		break;
+	case RTN_BLACKHOLE:
+		return BPF_FIB_LKUP_RET_BLACKHOLE;
+	case RTN_UNREACHABLE:
+		return BPF_FIB_LKUP_RET_UNREACHABLE;
+	case RTN_PROHIBIT:
+		return BPF_FIB_LKUP_RET_PROHIBIT;
+	default:
 		return BPF_FIB_LKUP_RET_NOT_FWDED;
+	}
 
 	ipv6_stub->fib6_select_path(net, &res, &fl6, fl6.flowi6_oif,
 				    fl6.flowi6_oif != 0, NULL, strict);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index f500f587de23..22023bdc4890 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -500,31 +500,33 @@ static void rt6_device_match(struct net *net, struct fib6_result *res,
 
 	if (!oif && ipv6_addr_any(saddr)) {
 		nh = &f6i->fib6_nh;
-		if (!(nh->fib_nh_flags & RTNH_F_DEAD)) {
-			res->nh = nh;
-			return;
-		}
+		if (!(nh->fib_nh_flags & RTNH_F_DEAD))
+			goto out;
 	}
 
 	for (spf6i = f6i; spf6i; spf6i = rcu_dereference(spf6i->fib6_next)) {
 		nh = &spf6i->fib6_nh;
 		if (__rt6_device_match(net, nh, saddr, oif, flags)) {
 			res->f6i = spf6i;
-			res->nh = nh;
+			goto out;
 		}
 	}
 
 	if (oif && flags & RT6_LOOKUP_F_IFACE) {
 		res->f6i = net->ipv6.fib6_null_entry;
-		res->nh = &res->f6i->fib6_nh;
-		return;
+		nh = &res->f6i->fib6_nh;
+		goto out;
 	}
 
-	res->nh = &f6i->fib6_nh;
-	if (res->nh->fib_nh_flags & RTNH_F_DEAD) {
+	nh = &f6i->fib6_nh;
+	if (nh->fib_nh_flags & RTNH_F_DEAD) {
 		res->f6i = net->ipv6.fib6_null_entry;
-		res->nh = &res->f6i->fib6_nh;
+		nh = &res->f6i->fib6_nh;
 	}
+out:
+	res->nh = nh;
+	res->fib6_type = res->f6i->fib6_type;
+	res->fib6_flags = res->f6i->fib6_flags;
 }
 
 #ifdef CONFIG_IPV6_ROUTER_PREF
@@ -719,6 +721,8 @@ static void __find_rr_leaf(struct fib6_info *f6i_start,
 		if (find_match(nh, f6i->fib6_flags, oif, strict, mpri, do_rr)) {
 			res->f6i = f6i;
 			res->nh = nh;
+			res->fib6_flags = f6i->fib6_flags;
+			res->fib6_type = f6i->fib6_type;
 		}
 	}
 }
@@ -796,6 +800,8 @@ static void rt6_select(struct net *net, struct fib6_node *fn, int oif,
 	if (!res->f6i) {
 		res->f6i = net->ipv6.fib6_null_entry;
 		res->nh = &res->f6i->fib6_nh;
+		res->fib6_flags = res->f6i->fib6_flags;
+		res->fib6_type = res->f6i->fib6_type;
 	}
 }
 
@@ -889,15 +895,14 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
 static struct net_device *ip6_rt_get_dev_rcu(const struct fib6_result *res)
 {
 	struct net_device *dev = res->nh->fib_nh_dev;
-	const struct fib6_info *f6i = res->f6i;
 
-	if (f6i->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) {
+	if (res->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) {
 		/* for copies of local routes, dst->dev needs to be the
 		 * device if it is a master device, the master device if
 		 * device is enslaved, and the loopback as the default
 		 */
 		if (netif_is_l3_slave(dev) &&
-		    !rt6_need_strict(&f6i->fib6_dst.addr))
+		    !rt6_need_strict(&res->f6i->fib6_dst.addr))
 			dev = l3mdev_master_dev_rcu(dev);
 		else if (!netif_is_l3_master(dev))
 			dev = dev_net(dev)->loopback_dev;
@@ -943,11 +948,11 @@ static unsigned short fib6_info_dst_flags(struct fib6_info *rt)
 	return flags;
 }
 
-static void ip6_rt_init_dst_reject(struct rt6_info *rt, struct fib6_info *ort)
+static void ip6_rt_init_dst_reject(struct rt6_info *rt, u8 fib6_type)
 {
-	rt->dst.error = ip6_rt_type_to_error(ort->fib6_type);
+	rt->dst.error = ip6_rt_type_to_error(fib6_type);
 
-	switch (ort->fib6_type) {
+	switch (fib6_type) {
 	case RTN_BLACKHOLE:
 		rt->dst.output = dst_discard_out;
 		rt->dst.input = dst_discard;
@@ -967,19 +972,19 @@ static void ip6_rt_init_dst_reject(struct rt6_info *rt, struct fib6_info *ort)
 
 static void ip6_rt_init_dst(struct rt6_info *rt, const struct fib6_result *res)
 {
-	struct fib6_info *ort = res->f6i;
+	struct fib6_info *f6i = res->f6i;
 
-	if (ort->fib6_flags & RTF_REJECT) {
-		ip6_rt_init_dst_reject(rt, ort);
+	if (res->fib6_flags & RTF_REJECT) {
+		ip6_rt_init_dst_reject(rt, res->fib6_type);
 		return;
 	}
 
 	rt->dst.error = 0;
 	rt->dst.output = ip6_output;
 
-	if (ort->fib6_type == RTN_LOCAL || ort->fib6_type == RTN_ANYCAST) {
+	if (res->fib6_type == RTN_LOCAL || res->fib6_type == RTN_ANYCAST) {
 		rt->dst.input = ip6_input;
-	} else if (ipv6_addr_type(&ort->fib6_dst.addr) & IPV6_ADDR_MULTICAST) {
+	} else if (ipv6_addr_type(&f6i->fib6_dst.addr) & IPV6_ADDR_MULTICAST) {
 		rt->dst.input = ip6_mc_input;
 	} else {
 		rt->dst.input = ip6_forward;
@@ -1012,7 +1017,7 @@ static void ip6_rt_copy_init(struct rt6_info *rt, const struct fib6_result *res)
 
 	rt->rt6i_dst = f6i->fib6_dst;
 	rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL;
-	rt->rt6i_flags = f6i->fib6_flags;
+	rt->rt6i_flags = res->fib6_flags;
 	if (nh->fib_nh_gw_family) {
 		rt->rt6i_gateway = nh->fib_nh_gw6;
 		rt->rt6i_flags |= RTF_GATEWAY;
@@ -2361,6 +2366,9 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
 		rcu_read_lock();
 		res.f6i = rcu_dereference(rt6->from);
 		res.nh = &res.f6i->fib6_nh;
+		res.fib6_flags = res.f6i->fib6_flags;
+		res.fib6_type = res.f6i->fib6_type;
+
 		nrt6 = ip6_rt_cache_alloc(&res, daddr, saddr);
 		if (nrt6) {
 			rt6_do_update_pmtu(nrt6, mtu);
@@ -2526,10 +2534,13 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
 	res.f6i = rt;
 	res.nh = &rt->fib6_nh;
 out:
-	if (ret)
+	if (ret) {
 		ip6_hold_safe(net, &ret);
-	else
+	} else {
+		res.fib6_flags = res.f6i->fib6_flags;
+		res.fib6_type = res.f6i->fib6_type;
 		ret = ip6_create_rt_rcu(&res);
+	}
 
 	rcu_read_unlock();
 
@@ -3487,6 +3498,8 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
 	rcu_read_unlock();
 
 	res.nh = &res.f6i->fib6_nh;
+	res.fib6_flags = res.f6i->fib6_flags;
+	res.fib6_type = res.f6i->fib6_type;
 	nrt = ip6_rt_cache_alloc(&res, &msg->dest, NULL);
 	if (!nrt)
 		goto out;
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups
  2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
                   ` (12 preceding siblings ...)
  2019-04-16 21:36 ` [PATCH v2 net-next 13/13] ipv6: Add fib6_type and fib6_flags to fib6_result David Ahern
@ 2019-04-18  6:16 ` David Miller
  13 siblings, 0 replies; 15+ messages in thread
From: David Miller @ 2019-04-18  6:16 UTC (permalink / raw)
  To: dsahern; +Cc: netdev, idosch, dsahern

From: David Ahern <dsahern@kernel.org>
Date: Tue, 16 Apr 2019 14:35:58 -0700

> From: David Ahern <dsahern@gmail.com>
> 
> Add fib6_result as a single data structure to hold results from a fib
> lookup. IPv6 currently has everything in 1 data structure - a fib6_info,
> but with nexthop objects the fib6_nh can be in a nexthop or a nexthop
> can be a blackhole which affects the fib6_type and flags (REJECT).
> 
> v2
> - fixed 2 bugs in patch12:
>   i. checking return from fib6_table_lookup in fib6_lookup
>   ii. call to fib6_rule_saddr in fib6_rule_action_alt should use res->nh

Looks good, series applied.

Thanks David.

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2019-04-18  6:16 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-16 21:35 [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
2019-04-16 21:35 ` [PATCH v2 net-next 01/13] ipv6: Rename fib6_multipath_select and pass fib6_result David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 02/13] ipv6: Pass fib6_result to rt6_find_cached_rt David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 03/13] ipv6: Pass fib6_result to ip6_rt_cache_alloc David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 04/13] ipv6: Pass fib6_result to ip6_create_rt_rcu David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 05/13] ipv6: Pass fib6_result to pcpu route functions David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 06/13] ipv6: Pass fib6_result to ip6_rt_get_dev_rcu and ip6_rt_copy_init David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 07/13] ipv6: Pass fib6_result to rt6_insert_exception David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 08/13] ipv6: Pass fib6_result to ip6_mtu_from_fib6 and fib6_mtu David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 09/13] ipv6: Pass fib6_result to rt6_device_match David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 10/13] ipv6: Pass fib6_result to rt6_select and find_rr_leaf David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 11/13] ipv6: Pass fib6_result to fib6_table_lookup tracepoint David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 12/13] ipv6: Pass fib6_result to fib lookups David Ahern
2019-04-16 21:36 ` [PATCH v2 net-next 13/13] ipv6: Add fib6_type and fib6_flags to fib6_result David Ahern
2019-04-18  6:16 ` [PATCH v2 net-next 00/13] ipv6: Use fib6_result for fib_lookups David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).