On Tue, Apr 09, 2019 at 02:41:19PM -0700, David Ahern wrote: > From: David Ahern <dsah...@gmail.com> > > Move the nexthop evaluation of a fib entry to a helper that can be > leveraged for each fib6_nh in a multipath nexthop object. > > In the move, 'continue' statements means the helper returns false > (loop should continue) and 'break' means return true (found the entry > of interest). > > Signed-off-by: David Ahern <dsah...@gmail.com> > --- > net/ipv6/route.c | 56 > +++++++++++++++++++++++++++++++++----------------------- > 1 file changed, 33 insertions(+), 23 deletions(-) > > diff --git a/net/ipv6/route.c b/net/ipv6/route.c > index 0e8becb1e455..d555edaaff13 100644 > --- a/net/ipv6/route.c > +++ b/net/ipv6/route.c > @@ -2407,6 +2407,35 @@ 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, Why both "struct fib6_info" and "struct fib6_nh" are needed? I assume nh cannot be obtained from f6i in the later patch when nh is decoupled from f6i?
> + struct flowi6 *fl6, > + const struct in6_addr *gw, > + struct rt6_info **ret) > +{ > + if (nh->fib_nh_flags & RTNH_F_DEAD || !nh->fib_nh_gw_family || > + fl6->flowi6_oif != nh->fib_nh_dev->ifindex) > + return false; > + > + /* rt_cache's gateway might be different from its 'parent' > + * in the case of an ip redirect. > + * So we keep searching in the exception table if the gateway > + * is different. > + */ > + if (!ipv6_addr_equal(gw, &nh->fib_nh_gw6)) { > + struct rt6_info *rt_cache; > + > + rt_cache = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr); > + if (rt_cache && > + ipv6_addr_equal(gw, &rt_cache->rt6i_gateway)) { > + *ret = rt_cache; > + return true; > + } > + return false; > + } > + return true; > +} > + > /* Handle redirects */ > struct ip6rd_flowi { > struct flowi6 fl6; > @@ -2420,7 +2449,7 @@ static struct rt6_info *__ip6_route_redirect(struct net > *net, > int flags) > { > struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6; > - struct rt6_info *ret = NULL, *rt_cache; > + struct rt6_info *ret = NULL; > struct fib6_info *rt; The "rt" naming is becoming hard to review. It is fortunate that the type context is kept in this diff. In this local case, the s/rt/f6i/ rename is quite doable? It can be the first clean-up step. > struct fib6_node *fn; > > @@ -2438,34 +2467,15 @@ 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) { > - if (rt->fib6_nh.fib_nh_flags & RTNH_F_DEAD) > - continue; > if (fib6_check_expired(rt)) > continue; > if (rt->fib6_flags & RTF_REJECT) > break; > - if (!rt->fib6_nh.fib_nh_gw_family) > - continue; > if (fl6->flowi6_oif != rt->fib6_nh.fib_nh_dev->ifindex) This check is also copied to the new ip6_redirect_nh_match. Should this one be removed from here? > continue; > - /* rt_cache's gateway might be different from its 'parent' > - * in the case of an ip redirect. > - * So we keep searching in the exception table if the gateway > - * is different. > - */ > - if (!ipv6_addr_equal(&rdfl->gateway, &rt->fib6_nh.fib_nh_gw6)) { > - rt_cache = rt6_find_cached_rt(rt, > - &fl6->daddr, > - &fl6->saddr); > - if (rt_cache && > - ipv6_addr_equal(&rdfl->gateway, > - &rt_cache->rt6i_gateway)) { > - ret = rt_cache; > - break; > - } > - continue; > - } > - break; > + if (ip6_redirect_nh_match(rt, &rt->fib6_nh, fl6, > + &rdfl->gateway, &ret)) > + goto out; > } > > if (!rt) > -- > 2.11.0 >