ipv6: Pass fib6_result to fib lookups
authorDavid Ahern <dsahern@gmail.com>
Tue, 16 Apr 2019 21:36:10 +0000 (14:36 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 18 Apr 2019 06:10:47 +0000 (23:10 -0700)
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>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip6_fib.h
include/net/ipv6_stubs.h
net/core/filter.c
net/ipv6/addrconf_core.c
net/ipv6/fib6_rules.c
net/ipv6/ip6_fib.c
net/ipv6/route.c

index c4d8180..cb3277c 100644 (file)
@@ -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,
index 0d16b9e..6c0c4fd 100644 (file)
@@ -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);
index bb8fb2d..d17347c 100644 (file)
@@ -4684,7 +4684,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 */
@@ -4726,18 +4726,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;
 
index c4c0203..763a947 100644 (file)
@@ -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
index f590446..ab5ac64 100644 (file)
@@ -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 || res->f6i == net->ipv6.fib6_null_entry)
+                       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;
-       }
+                                     res->nh->fib_nh_dev);
 
        return err;
 }
index 46f54a5..b47e15d 100644 (file)
@@ -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)
index 405e078..5a1e117 100644 (file)
@@ -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 @@ redo_rt6_select:
                }
        }
 
-       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();