Message ID | 20141008.153254.1700572195760396537.davem@davemloft.net |
---|---|
State | RFC, archived |
Delegated to: | David Miller |
Headers | show |
Hi, > Ok this looks fine, and I can see how there is a dependency with patch > #1. > > But I also want to point out how this change show my point about > BACKTRACK() even more. Read this function after this patch is > applied and someone auditing might say "oh, 'out' label is now > unused, we can remove it" > > Again, hidden control flow is really bad, and we've had very serious > bugs in the past because of it (which we've fixed by ditching the > side effect causing macros in favor of properly designed inline > functions). Agree. > Trying to be constructive, why don't we go in a direction like > the following? Looks good. There is another place calling BACKTRACK. Similar change also needs to happen there or some more re-factoring is needed. I also have another idea to further reduce the number of fib6_lookup() in the CONFIG_IPV6_MULTIPLE_TABLES case. I will give it another attempt together. Thanks, Martin > > diff --git a/net/ipv6/route.c b/net/ipv6/route.c > index a318dd89..99612c5 100644 > --- a/net/ipv6/route.c > +++ b/net/ipv6/route.c > @@ -772,6 +772,26 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, > } > #endif > > +static struct fib6_node *rt6_backtrack(struct net *net, struct rt6_info *rt, struct fib6_node *fn, const struct in6_addr *saddr) > +{ > + if (rt == net->ipv6.ip6_null_entry) { > + struct fib6_node *pn; > + > + while (1) { > + if (fn->fn_flags & RTN_TL_ROOT) > + break; > + pn = fn->parent; > + if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) > + fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, saddr); > + else > + fn = pn; > + if (fn->fn_flags & RTN_RTINFO) > + break; > + } > + } > + return fn; > +} > + > #define BACKTRACK(__net, saddr) \ > do { \ > if (rt == __net->ipv6.ip6_null_entry) { \ > @@ -934,10 +954,15 @@ restart: > rt = rt6_select(fn, oif, strict | reachable); > if (rt->rt6i_nsiblings) > rt = rt6_multipath_select(rt, fl6, oif, strict | reachable); > - BACKTRACK(net, &fl6->saddr); > - if (rt == net->ipv6.ip6_null_entry || > - rt->rt6i_flags & RTF_CACHE) > - goto out; > + fn = rt6_backtrack(net, rt, fn, &fl6->saddr); > + if (rt == net->ipv6.ip6_null_entry) { > + if (fn->fn_flags & RTN_TL_ROOT) > + goto out; > + if (fn->fn_flags & RTN_RTINFO) > + goto restart; > + } > + if (rt->rt6i_flags & RTF_CACHE) > + goto out1; > > dst_hold(&rt->dst); > read_unlock_bh(&table->tb6_lock); > @@ -974,6 +999,7 @@ out: > reachable = 0; > goto restart_2; > } > +out1: > dst_hold(&rt->dst); > read_unlock_bh(&table->tb6_lock); > out2: -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a318dd89..99612c5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -772,6 +772,26 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, } #endif +static struct fib6_node *rt6_backtrack(struct net *net, struct rt6_info *rt, struct fib6_node *fn, const struct in6_addr *saddr) +{ + if (rt == net->ipv6.ip6_null_entry) { + struct fib6_node *pn; + + while (1) { + if (fn->fn_flags & RTN_TL_ROOT) + break; + pn = fn->parent; + if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) + fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, saddr); + else + fn = pn; + if (fn->fn_flags & RTN_RTINFO) + break; + } + } + return fn; +} + #define BACKTRACK(__net, saddr) \ do { \ if (rt == __net->ipv6.ip6_null_entry) { \ @@ -934,10 +954,15 @@ restart: rt = rt6_select(fn, oif, strict | reachable); if (rt->rt6i_nsiblings) rt = rt6_multipath_select(rt, fl6, oif, strict | reachable); - BACKTRACK(net, &fl6->saddr); - if (rt == net->ipv6.ip6_null_entry || - rt->rt6i_flags & RTF_CACHE) - goto out; + fn = rt6_backtrack(net, rt, fn, &fl6->saddr); + if (rt == net->ipv6.ip6_null_entry) { + if (fn->fn_flags & RTN_TL_ROOT) + goto out; + if (fn->fn_flags & RTN_RTINFO) + goto restart; + } + if (rt->rt6i_flags & RTF_CACHE) + goto out1; dst_hold(&rt->dst); read_unlock_bh(&table->tb6_lock); @@ -974,6 +999,7 @@ out: reachable = 0; goto restart_2; } +out1: dst_hold(&rt->dst); read_unlock_bh(&table->tb6_lock); out2: