|
@@ -63,19 +63,32 @@ unsigned int fib6_rules_seq_read(struct net *net)
|
|
|
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
|
|
|
int flags, pol_lookup_t lookup)
|
|
|
{
|
|
|
- struct fib_lookup_arg arg = {
|
|
|
- .lookup_ptr = lookup,
|
|
|
- .flags = FIB_LOOKUP_NOREF,
|
|
|
- };
|
|
|
-
|
|
|
- /* update flow if oif or iif point to device enslaved to l3mdev */
|
|
|
- l3mdev_update_flow(net, flowi6_to_flowi(fl6));
|
|
|
-
|
|
|
- fib_rules_lookup(net->ipv6.fib6_rules_ops,
|
|
|
- flowi6_to_flowi(fl6), flags, &arg);
|
|
|
-
|
|
|
- if (arg.result)
|
|
|
- return arg.result;
|
|
|
+ if (net->ipv6.fib6_has_custom_rules) {
|
|
|
+ struct fib_lookup_arg arg = {
|
|
|
+ .lookup_ptr = lookup,
|
|
|
+ .flags = FIB_LOOKUP_NOREF,
|
|
|
+ };
|
|
|
+
|
|
|
+ /* update flow if oif or iif point to device enslaved to l3mdev */
|
|
|
+ l3mdev_update_flow(net, flowi6_to_flowi(fl6));
|
|
|
+
|
|
|
+ fib_rules_lookup(net->ipv6.fib6_rules_ops,
|
|
|
+ flowi6_to_flowi(fl6), flags, &arg);
|
|
|
+
|
|
|
+ if (arg.result)
|
|
|
+ return arg.result;
|
|
|
+ } else {
|
|
|
+ struct rt6_info *rt;
|
|
|
+
|
|
|
+ rt = lookup(net, net->ipv6.fib6_local_tbl, fl6, flags);
|
|
|
+ if (rt != net->ipv6.ip6_null_entry && rt->dst.error != -EAGAIN)
|
|
|
+ return &rt->dst;
|
|
|
+ ip6_rt_put(rt);
|
|
|
+ rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
|
|
|
+ if (rt->dst.error != -EAGAIN)
|
|
|
+ return &rt->dst;
|
|
|
+ ip6_rt_put(rt);
|
|
|
+ }
|
|
|
|
|
|
dst_hold(&net->ipv6.ip6_null_entry->dst);
|
|
|
return &net->ipv6.ip6_null_entry->dst;
|
|
@@ -245,6 +258,7 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
|
|
|
rule6->dst.plen = frh->dst_len;
|
|
|
rule6->tclass = frh->tos;
|
|
|
|
|
|
+ net->ipv6.fib6_has_custom_rules = true;
|
|
|
err = 0;
|
|
|
errout:
|
|
|
return err;
|