Commit effda4dd authored by David Ahern's avatar David Ahern Committed by David S. Miller

ipv6: Pass fib6_result to fib lookups

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: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8ff2e5b2
...@@ -389,12 +389,13 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, ...@@ -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 /* called with rcu lock held; can return error pointer
* caller needs to select path * caller needs to select path
*/ */
struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6, int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
int flags); struct fib6_result *res, int flags);
/* called with rcu lock held; caller needs to select path */ /* called with rcu lock held; caller needs to select path */
struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table, int fib6_table_lookup(struct net *net, struct fib6_table *table,
int oif, struct flowi6 *fl6, int strict); int oif, struct flowi6 *fl6, struct fib6_result *res,
int strict);
void fib6_select_path(const struct net *net, struct fib6_result *res, void fib6_select_path(const struct net *net, struct fib6_result *res,
struct flowi6 *fl6, int oif, bool have_oif_match, struct flowi6 *fl6, int oif, bool have_oif_match,
......
...@@ -29,12 +29,11 @@ struct ipv6_stub { ...@@ -29,12 +29,11 @@ struct ipv6_stub {
int (*ipv6_route_input)(struct sk_buff *skb); int (*ipv6_route_input)(struct sk_buff *skb);
struct fib6_table *(*fib6_get_table)(struct net *net, u32 id); struct fib6_table *(*fib6_get_table)(struct net *net, u32 id);
struct fib6_info *(*fib6_lookup)(struct net *net, int oif, int (*fib6_lookup)(struct net *net, int oif, struct flowi6 *fl6,
struct flowi6 *fl6, int flags); struct fib6_result *res, int flags);
struct fib6_info *(*fib6_table_lookup)(struct net *net, int (*fib6_table_lookup)(struct net *net, struct fib6_table *table,
struct fib6_table *table, int oif, struct flowi6 *fl6,
int oif, struct flowi6 *fl6, struct fib6_result *res, int flags);
int flags);
void (*fib6_select_path)(const struct net *net, struct fib6_result *res, void (*fib6_select_path)(const struct net *net, struct fib6_result *res,
struct flowi6 *fl6, int oif, bool oif_match, struct flowi6 *fl6, int oif, bool oif_match,
const struct sk_buff *skb, int strict); const struct sk_buff *skb, int strict);
......
...@@ -4684,7 +4684,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params, ...@@ -4684,7 +4684,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
struct inet6_dev *idev; struct inet6_dev *idev;
struct flowi6 fl6; struct flowi6 fl6;
int strict = 0; int strict = 0;
int oif; int oif, err;
u32 mtu; u32 mtu;
/* link local addresses are never forwarded */ /* link local addresses are never forwarded */
...@@ -4726,18 +4726,18 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params, ...@@ -4726,18 +4726,18 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
if (unlikely(!tb)) if (unlikely(!tb))
return BPF_FIB_LKUP_RET_NOT_FWDED; return BPF_FIB_LKUP_RET_NOT_FWDED;
res.f6i = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6, err = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6, &res,
strict); strict);
} else { } else {
fl6.flowi6_mark = 0; fl6.flowi6_mark = 0;
fl6.flowi6_secid = 0; fl6.flowi6_secid = 0;
fl6.flowi6_tun_key.tun_id = 0; fl6.flowi6_tun_key.tun_id = 0;
fl6.flowi6_uid = sock_net_uid(net, NULL); 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)) res.f6i == net->ipv6.fib6_null_entry))
return BPF_FIB_LKUP_RET_NOT_FWDED; return BPF_FIB_LKUP_RET_NOT_FWDED;
......
...@@ -144,18 +144,19 @@ static struct fib6_table *eafnosupport_fib6_get_table(struct net *net, u32 id) ...@@ -144,18 +144,19 @@ static struct fib6_table *eafnosupport_fib6_get_table(struct net *net, u32 id)
return NULL; return NULL;
} }
static struct fib6_info * static int
eafnosupport_fib6_table_lookup(struct net *net, struct fib6_table *table, 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, 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 static void
......
...@@ -61,16 +61,16 @@ unsigned int fib6_rules_seq_read(struct net *net) ...@@ -61,16 +61,16 @@ unsigned int fib6_rules_seq_read(struct net *net)
} }
/* called with rcu lock held; no reference taken on fib6_info */ /* 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 fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
int flags) struct fib6_result *res, int flags)
{ {
struct fib6_info *f6i;
int err; int err;
if (net->ipv6.fib6_has_custom_rules) { if (net->ipv6.fib6_has_custom_rules) {
struct fib_lookup_arg arg = { struct fib_lookup_arg arg = {
.lookup_ptr = fib6_table_lookup, .lookup_ptr = fib6_table_lookup,
.lookup_data = &oif, .lookup_data = &oif,
.result = res,
.flags = FIB_LOOKUP_NOREF, .flags = FIB_LOOKUP_NOREF,
}; };
...@@ -78,19 +78,15 @@ struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6, ...@@ -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, err = fib_rules_lookup(net->ipv6.fib6_rules_ops,
flowi6_to_flowi(fl6), flags, &arg); flowi6_to_flowi(fl6), flags, &arg);
if (err)
return ERR_PTR(err);
f6i = arg.result ? : net->ipv6.fib6_null_entry;
} else { } else {
f6i = fib6_table_lookup(net, net->ipv6.fib6_local_tbl, err = fib6_table_lookup(net, net->ipv6.fib6_local_tbl, oif,
oif, fl6, flags); fl6, res, flags);
if (!f6i || f6i == net->ipv6.fib6_null_entry) if (err || res->f6i == net->ipv6.fib6_null_entry)
f6i = fib6_table_lookup(net, net->ipv6.fib6_main_tbl, err = fib6_table_lookup(net, net->ipv6.fib6_main_tbl,
oif, fl6, flags); oif, fl6, res, flags);
} }
return f6i; return err;
} }
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, 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, ...@@ -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, static int fib6_rule_action_alt(struct fib_rule *rule, struct flowi *flp,
int flags, struct fib_lookup_arg *arg) int flags, struct fib_lookup_arg *arg)
{ {
struct fib6_result *res = arg->result;
struct flowi6 *flp6 = &flp->u.ip6; struct flowi6 *flp6 = &flp->u.ip6;
struct net *net = rule->fr_net; struct net *net = rule->fr_net;
struct fib6_table *table; struct fib6_table *table;
struct fib6_info *f6i;
int err = -EAGAIN, *oif; int err = -EAGAIN, *oif;
u32 tb_id; u32 tb_id;
...@@ -182,14 +178,10 @@ static int fib6_rule_action_alt(struct fib_rule *rule, struct flowi *flp, ...@@ -182,14 +178,10 @@ static int fib6_rule_action_alt(struct fib_rule *rule, struct flowi *flp,
return -EAGAIN; return -EAGAIN;
oif = (int *)arg->lookup_data; oif = (int *)arg->lookup_data;
f6i = fib6_table_lookup(net, table, *oif, flp6, flags); err = fib6_table_lookup(net, table, *oif, flp6, res, flags);
if (f6i != net->ipv6.fib6_null_entry) { if (!err && res->f6i != net->ipv6.fib6_null_entry)
err = fib6_rule_saddr(net, rule, flags, flp6, err = fib6_rule_saddr(net, rule, flags, flp6,
fib6_info_nh_dev(f6i)); res->nh->fib_nh_dev);
if (likely(!err))
arg->result = f6i;
}
return err; return err;
} }
......
...@@ -354,10 +354,11 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, ...@@ -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 */ /* 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 fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
int flags) 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) static void __net_init fib6_tables_init(struct net *net)
......
...@@ -1839,11 +1839,10 @@ void rt6_age_exceptions(struct fib6_info *rt, ...@@ -1839,11 +1839,10 @@ void rt6_age_exceptions(struct fib6_info *rt,
} }
/* must be called with rcu lock held */ /* must be called with rcu lock held */
struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table, int fib6_table_lookup(struct net *net, struct fib6_table *table, int oif,
int oif, struct flowi6 *fl6, int strict) struct flowi6 *fl6, struct fib6_result *res, int strict)
{ {
struct fib6_node *fn, *saved_fn; struct fib6_node *fn, *saved_fn;
struct fib6_result res;
fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
saved_fn = fn; saved_fn = fn;
...@@ -1852,8 +1851,8 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table, ...@@ -1852,8 +1851,8 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
oif = 0; oif = 0;
redo_rt6_select: redo_rt6_select:
rt6_select(net, fn, oif, &res, strict); rt6_select(net, fn, oif, res, strict);
if (res.f6i == net->ipv6.fib6_null_entry) { if (res->f6i == net->ipv6.fib6_null_entry) {
fn = fib6_backtrack(fn, &fl6->saddr); fn = fib6_backtrack(fn, &fl6->saddr);
if (fn) if (fn)
goto redo_rt6_select; goto redo_rt6_select;
...@@ -1865,9 +1864,9 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table, ...@@ -1865,9 +1864,9 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
} }
} }
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, 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, ...@@ -1885,7 +1884,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
rcu_read_lock(); 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) { if (res.f6i == net->ipv6.fib6_null_entry) {
rt = net->ipv6.ip6_null_entry; rt = net->ipv6.ip6_null_entry;
rcu_read_unlock(); rcu_read_unlock();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment