|
@@ -772,23 +772,22 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-#define BACKTRACK(__net, saddr) \
|
|
|
-do { \
|
|
|
- if (rt == __net->ipv6.ip6_null_entry) { \
|
|
|
- struct fib6_node *pn; \
|
|
|
- while (1) { \
|
|
|
- if (fn->fn_flags & RTN_TL_ROOT) \
|
|
|
- goto out; \
|
|
|
- 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) \
|
|
|
- goto restart; \
|
|
|
- } \
|
|
|
- } \
|
|
|
-} while (0)
|
|
|
+static struct fib6_node* fib6_backtrack(struct fib6_node *fn,
|
|
|
+ struct in6_addr *saddr)
|
|
|
+{
|
|
|
+ struct fib6_node *pn;
|
|
|
+ while (1) {
|
|
|
+ if (fn->fn_flags & RTN_TL_ROOT)
|
|
|
+ return NULL;
|
|
|
+ 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)
|
|
|
+ return fn;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
static struct rt6_info *ip6_pol_route_lookup(struct net *net,
|
|
|
struct fib6_table *table,
|
|
@@ -804,8 +803,11 @@ restart:
|
|
|
rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
|
|
|
if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
|
|
|
rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif, flags);
|
|
|
- BACKTRACK(net, &fl6->saddr);
|
|
|
-out:
|
|
|
+ if (rt == net->ipv6.ip6_null_entry) {
|
|
|
+ fn = fib6_backtrack(fn, &fl6->saddr);
|
|
|
+ if (fn)
|
|
|
+ goto restart;
|
|
|
+ }
|
|
|
dst_use(&rt->dst, jiffies);
|
|
|
read_unlock_bh(&table->tb6_lock);
|
|
|
return rt;
|
|
@@ -924,19 +926,25 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
|
|
|
|
|
|
strict |= flags & RT6_LOOKUP_F_IFACE;
|
|
|
|
|
|
-relookup:
|
|
|
+redo_fib6_lookup_lock:
|
|
|
read_lock_bh(&table->tb6_lock);
|
|
|
|
|
|
-restart_2:
|
|
|
+redo_fib6_lookup:
|
|
|
fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
|
|
|
|
|
|
-restart:
|
|
|
+redo_rt6_select:
|
|
|
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)
|
|
|
+ if (rt == net->ipv6.ip6_null_entry) {
|
|
|
+ fn = fib6_backtrack(fn, &fl6->saddr);
|
|
|
+ if (fn)
|
|
|
+ goto redo_rt6_select;
|
|
|
+ else
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (rt->rt6i_flags & RTF_CACHE)
|
|
|
goto out;
|
|
|
|
|
|
dst_hold(&rt->dst);
|
|
@@ -967,12 +975,12 @@ restart:
|
|
|
* released someone could insert this route. Relookup.
|
|
|
*/
|
|
|
ip6_rt_put(rt);
|
|
|
- goto relookup;
|
|
|
+ goto redo_fib6_lookup_lock;
|
|
|
|
|
|
out:
|
|
|
if (reachable) {
|
|
|
reachable = 0;
|
|
|
- goto restart_2;
|
|
|
+ goto redo_fib6_lookup;
|
|
|
}
|
|
|
dst_hold(&rt->dst);
|
|
|
read_unlock_bh(&table->tb6_lock);
|
|
@@ -1235,10 +1243,12 @@ restart:
|
|
|
rt = net->ipv6.ip6_null_entry;
|
|
|
else if (rt->dst.error) {
|
|
|
rt = net->ipv6.ip6_null_entry;
|
|
|
- goto out;
|
|
|
+ } else if (rt == net->ipv6.ip6_null_entry) {
|
|
|
+ fn = fib6_backtrack(fn, &fl6->saddr);
|
|
|
+ if (fn)
|
|
|
+ goto restart;
|
|
|
}
|
|
|
- BACKTRACK(net, &fl6->saddr);
|
|
|
-out:
|
|
|
+
|
|
|
dst_hold(&rt->dst);
|
|
|
|
|
|
read_unlock_bh(&table->tb6_lock);
|