* [PATCH net-next 01/13] ipv6: Rename fib6_multipath_select and pass fib6_result
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 02/13] ipv6: Pass fib6_result to rt6_find_cached_rt David Ahern
` (11 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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 net-next 02/13] ipv6: Pass fib6_result to rt6_find_cached_rt
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
2019-04-16 0:56 ` [PATCH net-next 01/13] ipv6: Rename fib6_multipath_select and pass fib6_result David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 03/13] ipv6: Pass fib6_result to ip6_rt_cache_alloc David Ahern
` (10 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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 net-next 03/13] ipv6: Pass fib6_result to ip6_rt_cache_alloc
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
2019-04-16 0:56 ` [PATCH net-next 01/13] ipv6: Rename fib6_multipath_select and pass fib6_result David Ahern
2019-04-16 0:56 ` [PATCH net-next 02/13] ipv6: Pass fib6_result to rt6_find_cached_rt David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 04/13] ipv6: Pass fib6_result to ip6_create_rt_rcu David Ahern
` (9 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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 net-next 04/13] ipv6: Pass fib6_result to ip6_create_rt_rcu
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
` (2 preceding siblings ...)
2019-04-16 0:56 ` [PATCH net-next 03/13] ipv6: Pass fib6_result to ip6_rt_cache_alloc David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 05/13] ipv6: Pass fib6_result to pcpu route functions David Ahern
` (8 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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 net-next 05/13] ipv6: Pass fib6_result to pcpu route functions
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
` (3 preceding siblings ...)
2019-04-16 0:56 ` [PATCH net-next 04/13] ipv6: Pass fib6_result to ip6_create_rt_rcu David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 06/13] ipv6: Pass fib6_result to ip6_rt_get_dev_rcu and ip6_rt_copy_init David Ahern
` (7 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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 net-next 06/13] ipv6: Pass fib6_result to ip6_rt_get_dev_rcu and ip6_rt_copy_init
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
` (4 preceding siblings ...)
2019-04-16 0:56 ` [PATCH net-next 05/13] ipv6: Pass fib6_result to pcpu route functions David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 07/13] ipv6: Pass fib6_result to rt6_insert_exception David Ahern
` (6 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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 net-next 07/13] ipv6: Pass fib6_result to rt6_insert_exception
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
` (5 preceding siblings ...)
2019-04-16 0:56 ` [PATCH net-next 06/13] ipv6: Pass fib6_result to ip6_rt_get_dev_rcu and ip6_rt_copy_init David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 08/13] ipv6: Pass fib6_result to ip6_mtu_from_fib6 and fib6_mtu David Ahern
` (5 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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 net-next 08/13] ipv6: Pass fib6_result to ip6_mtu_from_fib6 and fib6_mtu
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
` (6 preceding siblings ...)
2019-04-16 0:56 ` [PATCH net-next 07/13] ipv6: Pass fib6_result to rt6_insert_exception David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 09/13] ipv6: Pass fib6_result to rt6_device_match David Ahern
` (4 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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 net-next 09/13] ipv6: Pass fib6_result to rt6_device_match
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
` (7 preceding siblings ...)
2019-04-16 0:56 ` [PATCH net-next 08/13] ipv6: Pass fib6_result to ip6_mtu_from_fib6 and fib6_mtu David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 10/13] ipv6: Pass fib6_result to rt6_select and find_rr_leaf David Ahern
` (3 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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 net-next 10/13] ipv6: Pass fib6_result to rt6_select and find_rr_leaf
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
` (8 preceding siblings ...)
2019-04-16 0:56 ` [PATCH net-next 09/13] ipv6: Pass fib6_result to rt6_device_match David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 11/13] ipv6: Pass fib6_result to fib6_table_lookup tracepoint David Ahern
` (2 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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 net-next 11/13] ipv6: Pass fib6_result to fib6_table_lookup tracepoint
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
` (9 preceding siblings ...)
2019-04-16 0:56 ` [PATCH net-next 10/13] ipv6: Pass fib6_result to rt6_select and find_rr_leaf David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 12/13] ipv6: Pass fib6_result to fib lookups David Ahern
2019-04-16 0:56 ` [PATCH net-next 13/13] ipv6: Add fib6_type and fib6_flags to fib6_result David Ahern
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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 net-next 12/13] ipv6: Pass fib6_result to fib lookups
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
` (10 preceding siblings ...)
2019-04-16 0:56 ` [PATCH net-next 11/13] ipv6: Pass fib6_result to fib6_table_lookup tracepoint David Ahern
@ 2019-04-16 0:56 ` David Ahern
2019-04-16 15:00 ` David Ahern
2019-04-16 0:56 ` [PATCH net-next 13/13] ipv6: Add fib6_type and fib6_flags to fib6_result David Ahern
12 siblings, 1 reply; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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..61c0ba2621d0 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)
+ 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;
- }
+ fib6_info_nh_dev(res->f6i));
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
* Re: [PATCH net-next 12/13] ipv6: Pass fib6_result to fib lookups
2019-04-16 0:56 ` [PATCH net-next 12/13] ipv6: Pass fib6_result to fib lookups David Ahern
@ 2019-04-16 15:00 ` David Ahern
0 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 15:00 UTC (permalink / raw)
To: David Ahern, davem, netdev; +Cc: idosch
On 4/15/19 6:56 PM, David Ahern wrote:
> @@ -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;
> - }
> + fib6_info_nh_dev(res->f6i));
that is supposed to be res->nh, not fib6_info_nh_dev(res->f6i).
Will fix and send a v2.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH net-next 13/13] ipv6: Add fib6_type and fib6_flags to fib6_result
2019-04-16 0:56 [PATCH net-next 00/13] ipv6: Use fib6_result for fib_lookups David Ahern
` (11 preceding siblings ...)
2019-04-16 0:56 ` [PATCH net-next 12/13] ipv6: Pass fib6_result to fib lookups David Ahern
@ 2019-04-16 0:56 ` David Ahern
12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2019-04-16 0:56 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